From 7d8616ed500f01b201667020c9be545d686950be Mon Sep 17 00:00:00 2001 From: Balazs Benics Date: Fri, 19 Apr 2024 16:26:07 +0200 Subject: [PATCH 001/357] [analyzer] Fix stores through label locations (#89265) Interestingly, this case crashed from the very beginning of the project, at least starting by clang-3. As a "fix" I just do the same thing as we do for concrete integers. It might not be the best we could do, but arguably, it's still better than crashing. Fixes #89185 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 7 ++++--- clang/test/Analysis/gh-issue-89185.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 clang/test/Analysis/gh-issue-89185.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 193bbd6b1a47..e0a6d2f0fc7c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -695,6 +695,8 @@ Static Analyzer - Support C++23 static operator calls. (#GH84972) - Fixed a crash in ``security.cert.env.InvalidPtr`` checker when accidentally matched user-defined ``strerror`` and similar library functions. (GH#88181) +- Fixed a crash when storing through an address that refers to the address of + a label. (GH#89185) New features ^^^^^^^^^^^^ diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index ebba181eb2d8..ba29c1231390 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2358,11 +2358,12 @@ StoreRef RegionStoreManager::killBinding(Store ST, Loc L) { RegionBindingsRef RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) { - if (L.getAs()) + // We only care about region locations. + auto MemRegVal = L.getAs(); + if (!MemRegVal) return B; - // If we get here, the location should be a region. - const MemRegion *R = L.castAs().getRegion(); + const MemRegion *R = MemRegVal->getRegion(); // Check if the region is a struct region. if (const TypedValueRegion* TR = dyn_cast(R)) { diff --git a/clang/test/Analysis/gh-issue-89185.c b/clang/test/Analysis/gh-issue-89185.c new file mode 100644 index 000000000000..8a907f198a5f --- /dev/null +++ b/clang/test/Analysis/gh-issue-89185.c @@ -0,0 +1,14 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_dump(char); +void clang_analyzer_dump_ptr(char*); + +// https://github.com/llvm/llvm-project/issues/89185 +void binding_to_label_loc() { + char *b = &&MyLabel; +MyLabel: + *b = 0; // no-crash + clang_analyzer_dump_ptr(b); // expected-warning {{&&MyLabel}} + clang_analyzer_dump(*b); // expected-warning {{Unknown}} + // FIXME: We should never reach here, as storing to a label is invalid. +} -- GitLab From a309c07ad3fc4a9b0bf41a4e66e812b54338aa02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 19 Apr 2024 07:30:26 -0700 Subject: [PATCH 002/357] [flang][cuda] Allow if stmt in device subroutine (#89347) --- flang/lib/Semantics/check-cuda.cpp | 10 ++++++++++ flang/test/Semantics/cuf11.cuf | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp index fb1ebadd3785..a9e57de7e2f2 100644 --- a/flang/lib/Semantics/check-cuda.cpp +++ b/flang/lib/Semantics/check-cuda.cpp @@ -344,6 +344,9 @@ private: [&](const common::Indirection &x) { WarnOnIoStmt(source); }, + [&](const common::Indirection &x) { + Check(x.value()); + }, [&](const auto &x) { if (auto msg{ActionStmtChecker::WhyNotOk(x)}) { context_.Say(source, std::move(*msg)); @@ -369,6 +372,13 @@ private: Check(std::get(eb->t)); } } + void Check(const parser::IfStmt &is) { + const auto &uS{ + std::get>(is.t)}; + CheckUnwrappedExpr( + context_, uS.source, std::get(is.t)); + Check(uS.statement, uS.source); + } void Check(const parser::LoopControl::Bounds &bounds) { Check(bounds.lower); Check(bounds.upper); diff --git a/flang/test/Semantics/cuf11.cuf b/flang/test/Semantics/cuf11.cuf index de7ff2974324..554ac258e551 100644 --- a/flang/test/Semantics/cuf11.cuf +++ b/flang/test/Semantics/cuf11.cuf @@ -30,3 +30,7 @@ logical function compare_h(a,b) !ERROR: 'b' is not an object of derived type; it is implicitly typed compare_h = (a%h .eq. b%h) end + +attributes(global) subroutine sub2() + if (threadIdx%x == 1) print *, "I'm number one" +end subroutine -- GitLab From 5fa21e5fc7384069276e15dbb1c27986a6e86483 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Fri, 19 Apr 2024 07:35:55 -0700 Subject: [PATCH 003/357] [NFC][X86][Headers] Fix missing blank line It caused the \headerfile directive to be considered as part of the brief description in some of our tooling. --- clang/lib/Headers/avxintrin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Headers/avxintrin.h b/clang/lib/Headers/avxintrin.h index be7a0b247e03..4983f3311370 100644 --- a/clang/lib/Headers/avxintrin.h +++ b/clang/lib/Headers/avxintrin.h @@ -840,6 +840,7 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c) /// Copies the values stored in a 128-bit vector of [4 x float] as /// specified by the 128-bit integer vector operand. +/// /// \headerfile /// /// This intrinsic corresponds to the VPERMILPS instruction. -- GitLab From 78dca4af5a9fd77972f80e9f1ff33a00b95f669e Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Fri, 19 Apr 2024 10:40:16 -0400 Subject: [PATCH 004/357] [ClangOffloadBundler] Add file size to header (#88827) __hipRegisterFatBinary only accepts one pointer argument. It is expected to get the fat binary size from the header. This patch adds a file size field to the header of the compressed bundle. --- clang/docs/ClangOffloadBundler.rst | 5 +- clang/include/clang/Driver/OffloadBundler.h | 17 +++--- clang/lib/Driver/OffloadBundler.cpp | 54 +++++++++++++------ .../test/Driver/clang-offload-bundler-zstd.c | 19 ++++--- 4 files changed, 64 insertions(+), 31 deletions(-) diff --git a/clang/docs/ClangOffloadBundler.rst b/clang/docs/ClangOffloadBundler.rst index 1f8c85a08f8c..515e6c00a3b8 100644 --- a/clang/docs/ClangOffloadBundler.rst +++ b/clang/docs/ClangOffloadBundler.rst @@ -518,11 +518,14 @@ The compressed offload bundle begins with a header followed by the compressed bi This is a unique identifier to distinguish compressed offload bundles. The value is the string 'CCOB' (Compressed Clang Offload Bundle). - **Version Number (16-bit unsigned int)**: - This denotes the version of the compressed offload bundle format. The current version is `1`. + This denotes the version of the compressed offload bundle format. The current version is `2`. - **Compression Method (16-bit unsigned int)**: This field indicates the compression method used. The value corresponds to either `zlib` or `zstd`, represented as a 16-bit unsigned integer cast from the LLVM compression enumeration. +- **Total File Size (32-bit unsigned int)**: + This is the total size (in bytes) of the file, including the header. Available in version 2 and above. + - **Uncompressed Binary Size (32-bit unsigned int)**: This is the size (in bytes) of the binary data before it was compressed. diff --git a/clang/include/clang/Driver/OffloadBundler.h b/clang/include/clang/Driver/OffloadBundler.h index 65d33bfbd282..57ecbdcb7d04 100644 --- a/clang/include/clang/Driver/OffloadBundler.h +++ b/clang/include/clang/Driver/OffloadBundler.h @@ -100,6 +100,7 @@ struct OffloadTargetInfo { // - Version (2 bytes) // - Compression Method (2 bytes) - Uses the values from // llvm::compression::Format. +// - Total file size (4 bytes). Available in version 2 and above. // - Uncompressed Size (4 bytes). // - Truncated MD5 Hash (8 bytes). // - Compressed Data (variable length). @@ -109,13 +110,17 @@ private: static inline const size_t MagicSize = 4; static inline const size_t VersionFieldSize = sizeof(uint16_t); static inline const size_t MethodFieldSize = sizeof(uint16_t); - static inline const size_t SizeFieldSize = sizeof(uint32_t); - static inline const size_t HashFieldSize = 8; - static inline const size_t HeaderSize = MagicSize + VersionFieldSize + - MethodFieldSize + SizeFieldSize + - HashFieldSize; + static inline const size_t FileSizeFieldSize = sizeof(uint32_t); + static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t); + static inline const size_t HashFieldSize = sizeof(uint64_t); + static inline const size_t V1HeaderSize = + MagicSize + VersionFieldSize + MethodFieldSize + + UncompressedSizeFieldSize + HashFieldSize; + static inline const size_t V2HeaderSize = + MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize + + UncompressedSizeFieldSize + HashFieldSize; static inline const llvm::StringRef MagicNumber = "CCOB"; - static inline const uint16_t Version = 1; + static inline const uint16_t Version = 2; public: static llvm::Expected> diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp index 77c89356bc76..8cc82a0ee716 100644 --- a/clang/lib/Driver/OffloadBundler.cpp +++ b/clang/lib/Driver/OffloadBundler.cpp @@ -1010,6 +1010,10 @@ CompressedOffloadBundle::compress(llvm::compression::Params P, uint16_t CompressionMethod = static_cast(P.format); uint32_t UncompressedSize = Input.getBuffer().size(); + uint32_t TotalFileSize = MagicNumber.size() + sizeof(TotalFileSize) + + sizeof(Version) + sizeof(CompressionMethod) + + sizeof(UncompressedSize) + sizeof(TruncatedHash) + + CompressedBuffer.size(); SmallVector FinalBuffer; llvm::raw_svector_ostream OS(FinalBuffer); @@ -1017,6 +1021,8 @@ CompressedOffloadBundle::compress(llvm::compression::Params P, OS.write(reinterpret_cast(&Version), sizeof(Version)); OS.write(reinterpret_cast(&CompressionMethod), sizeof(CompressionMethod)); + OS.write(reinterpret_cast(&TotalFileSize), + sizeof(TotalFileSize)); OS.write(reinterpret_cast(&UncompressedSize), sizeof(UncompressedSize)); OS.write(reinterpret_cast(&TruncatedHash), @@ -1034,6 +1040,8 @@ CompressedOffloadBundle::compress(llvm::compression::Params P, (UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds; llvm::errs() << "Compressed bundle format version: " << Version << "\n" + << "Total file size (including headers): " + << formatWithCommas(TotalFileSize) << " bytes\n" << "Compression method used: " << MethodUsed << "\n" << "Compression level: " << P.level << "\n" << "Binary size before compression: " @@ -1059,9 +1067,9 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, StringRef Blob = Input.getBuffer(); - if (Blob.size() < HeaderSize) { + if (Blob.size() < V1HeaderSize) return llvm::MemoryBuffer::getMemBufferCopy(Blob); - } + if (llvm::identify_magic(Blob) != llvm::file_magic::offload_bundle_compressed) { if (Verbose) @@ -1069,21 +1077,32 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, return llvm::MemoryBuffer::getMemBufferCopy(Blob); } + size_t CurrentOffset = MagicSize; + uint16_t ThisVersion; + memcpy(&ThisVersion, Blob.data() + CurrentOffset, sizeof(uint16_t)); + CurrentOffset += VersionFieldSize; + uint16_t CompressionMethod; + memcpy(&CompressionMethod, Blob.data() + CurrentOffset, sizeof(uint16_t)); + CurrentOffset += MethodFieldSize; + + uint32_t TotalFileSize; + if (ThisVersion >= 2) { + if (Blob.size() < V2HeaderSize) + return createStringError(inconvertibleErrorCode(), + "Compressed bundle header size too small"); + memcpy(&TotalFileSize, Blob.data() + CurrentOffset, sizeof(uint32_t)); + CurrentOffset += FileSizeFieldSize; + } + uint32_t UncompressedSize; + memcpy(&UncompressedSize, Blob.data() + CurrentOffset, sizeof(uint32_t)); + CurrentOffset += UncompressedSizeFieldSize; + uint64_t StoredHash; - memcpy(&ThisVersion, Input.getBuffer().data() + MagicNumber.size(), - sizeof(uint16_t)); - memcpy(&CompressionMethod, Blob.data() + MagicSize + VersionFieldSize, - sizeof(uint16_t)); - memcpy(&UncompressedSize, - Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize, - sizeof(uint32_t)); - memcpy(&StoredHash, - Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize + - SizeFieldSize, - sizeof(uint64_t)); + memcpy(&StoredHash, Blob.data() + CurrentOffset, sizeof(uint64_t)); + CurrentOffset += HashFieldSize; llvm::compression::Format CompressionFormat; if (CompressionMethod == @@ -1102,7 +1121,7 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, DecompressTimer.startTimer(); SmallVector DecompressedData; - StringRef CompressedData = Blob.substr(HeaderSize); + StringRef CompressedData = Blob.substr(CurrentOffset); if (llvm::Error DecompressionError = llvm::compression::decompress( CompressionFormat, llvm::arrayRefFromStringRef(CompressedData), DecompressedData, UncompressedSize)) @@ -1135,8 +1154,11 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, double DecompressionSpeedMBs = (UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds; - llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n" - << "Decompression method: " + llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n"; + if (ThisVersion >= 2) + llvm::errs() << "Total file size (from header): " + << formatWithCommas(TotalFileSize) << " bytes\n"; + llvm::errs() << "Decompression method: " << (CompressionFormat == llvm::compression::Format::Zlib ? "zlib" : "zstd") diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c index 4485e57309bb..a424981c6971 100644 --- a/clang/test/Driver/clang-offload-bundler-zstd.c +++ b/clang/test/Driver/clang-offload-bundler-zstd.c @@ -22,19 +22,22 @@ // Check compression/decompression of offload bundle. // // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose 2>&1 | \ -// RUN: FileCheck -check-prefix=COMPRESS %s +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose >%t.1.txt 2>&1 // RUN: clang-offload-bundler -type=bc -list -input=%t.hip.bundle.bc | FileCheck -check-prefix=NOHOST %s // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose 2>&1 | \ -// RUN: FileCheck -check-prefix=DECOMPRESS %s +// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose >%t.2.txt 2>&1 +// RUN: cat %t.1.txt %t.2.txt | FileCheck %s // RUN: diff %t.tgt1 %t.res.tgt1 // RUN: diff %t.tgt2 %t.res.tgt2 // -// COMPRESS: Compression method used: zstd -// COMPRESS: Compression level: 3 -// DECOMPRESS: Decompression method: zstd -// DECOMPRESS: Hashes match: Yes +// CHECK: Compressed bundle format version: 2 +// CHECK: Total file size (including headers): [[SIZE:[0-9]*]] bytes +// CHECK: Compression method used: zstd +// CHECK: Compression level: 3 +// CHECK: Compressed bundle format version: 2 +// CHECK: Total file size (from header): [[SIZE]] bytes +// CHECK: Decompression method: zstd +// CHECK: Hashes match: Yes // NOHOST-NOT: host- // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906 -- GitLab From f4c0c40f388fff0975ecada4997683cef3cb1fae Mon Sep 17 00:00:00 2001 From: Adam Siemieniuk Date: Fri, 19 Apr 2024 16:41:37 +0200 Subject: [PATCH 005/357] [mlir][xegpu] XeGPU alias ops folder pass (#88886) Adds a pass that folds aliasing ops into XeGPU ops. --- mlir/docs/Passes.md | 4 + .../include/mlir/Dialect/XeGPU/CMakeLists.txt | 1 + .../Dialect/XeGPU/Transforms/CMakeLists.txt | 6 ++ .../mlir/Dialect/XeGPU/Transforms/Passes.h | 35 ++++++++ .../mlir/Dialect/XeGPU/Transforms/Passes.td | 26 ++++++ .../Dialect/XeGPU/Transforms/Transforms.h | 23 ++++++ mlir/include/mlir/InitAllPasses.h | 2 + mlir/lib/Dialect/XeGPU/CMakeLists.txt | 1 + .../Dialect/XeGPU/Transforms/CMakeLists.txt | 17 ++++ .../XeGPU/Transforms/XeGPUFoldAliasOps.cpp | 82 +++++++++++++++++++ .../Dialect/XeGPU/xegpu-fold-alias-ops.mlir | 20 +++++ 11 files changed, 217 insertions(+) create mode 100644 mlir/include/mlir/Dialect/XeGPU/Transforms/CMakeLists.txt create mode 100644 mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.h create mode 100644 mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td create mode 100644 mlir/include/mlir/Dialect/XeGPU/Transforms/Transforms.h create mode 100644 mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt create mode 100644 mlir/lib/Dialect/XeGPU/Transforms/XeGPUFoldAliasOps.cpp create mode 100644 mlir/test/Dialect/XeGPU/xegpu-fold-alias-ops.mlir diff --git a/mlir/docs/Passes.md b/mlir/docs/Passes.md index 84e6664436d7..6a18e06593e8 100644 --- a/mlir/docs/Passes.md +++ b/mlir/docs/Passes.md @@ -119,3 +119,7 @@ This document describes the available MLIR passes and their contracts. ## TOSA Dialect Passes [include "TosaPasses.md"] + +## XeGPU Dialect Passes + +[include "XeGPUPasses.md"] diff --git a/mlir/include/mlir/Dialect/XeGPU/CMakeLists.txt b/mlir/include/mlir/Dialect/XeGPU/CMakeLists.txt index f33061b2d87c..9f57627c321f 100644 --- a/mlir/include/mlir/Dialect/XeGPU/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/XeGPU/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(IR) +add_subdirectory(Transforms) diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/CMakeLists.txt b/mlir/include/mlir/Dialect/XeGPU/Transforms/CMakeLists.txt new file mode 100644 index 000000000000..9de7e87c7d39 --- /dev/null +++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_TARGET_DEFINITIONS Passes.td) +mlir_tablegen(Passes.h.inc -gen-pass-decls -name XeGPU) +add_public_tablegen_target(MLIRXeGPUPassIncGen) +add_dependencies(mlir-headers MLIRXeGPUPassIncGen) + +add_mlir_doc(Passes XeGPUPasses ./ -gen-pass-doc) diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.h b/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.h new file mode 100644 index 000000000000..bf55bde4b25b --- /dev/null +++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.h @@ -0,0 +1,35 @@ +//===- Passes.h - XeGPU Patterns and Passes ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_H +#define MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_H + +#include "mlir/Pass/Pass.h" + +namespace mlir { + +namespace xegpu { + +//===----------------------------------------------------------------------===// +// Passes +//===----------------------------------------------------------------------===// + +#define GEN_PASS_DECL +#include "mlir/Dialect/XeGPU/Transforms/Passes.h.inc" + +//===----------------------------------------------------------------------===// +// Registration +//===----------------------------------------------------------------------===// + +#define GEN_PASS_REGISTRATION +#include "mlir/Dialect/XeGPU/Transforms/Passes.h.inc" + +} // namespace xegpu +} // namespace mlir + +#endif // MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_H diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td new file mode 100644 index 000000000000..1ecd6ce95322 --- /dev/null +++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td @@ -0,0 +1,26 @@ +//===-- Passes.td - XeGPU transformation definition file ---*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + + +#ifndef MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_TD +#define MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_TD + +include "mlir/Pass/PassBase.td" + +def XeGPUFoldAliasOps : Pass<"xegpu-fold-alias-ops"> { + let summary = "Fold alias ops into XeGPU ops"; + let description = [{ + The pass folds aliasing ops into XeGPU ops that they operate on the original + source references. + }]; + let dependentDialects = [ + "memref::MemRefDialect", "xegpu::XeGPUDialect" + ]; +} + +#endif // MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_TD diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/Transforms.h b/mlir/include/mlir/Dialect/XeGPU/Transforms/Transforms.h new file mode 100644 index 000000000000..63ea26df0693 --- /dev/null +++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/Transforms.h @@ -0,0 +1,23 @@ +//===- Transforms.h - XeGPU Dialect transformations -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_XEGPU_TRANSFORMS_TRANSFORMS_H +#define MLIR_DIALECT_XEGPU_TRANSFORMS_TRANSFORMS_H + +namespace mlir { +class RewritePatternSet; + +namespace xegpu { + +/// Appends patterns for folding aliasing ops into XeGPU ops into `patterns`. +void populateXeGPUFoldAliasOpsPatterns(RewritePatternSet &patterns); + +} // namespace xegpu +} // namespace mlir + +#endif // MLIR_DIALECT_XEGPU_TRANSFORMS_TRANSFORMS_H diff --git a/mlir/include/mlir/InitAllPasses.h b/mlir/include/mlir/InitAllPasses.h index 5d90c197a6cc..90406f555b0f 100644 --- a/mlir/include/mlir/InitAllPasses.h +++ b/mlir/include/mlir/InitAllPasses.h @@ -45,6 +45,7 @@ #include "mlir/Dialect/Tosa/Transforms/Passes.h" #include "mlir/Dialect/Transform/Transforms/Passes.h" #include "mlir/Dialect/Vector/Transforms/Passes.h" +#include "mlir/Dialect/XeGPU/Transforms/Passes.h" #include "mlir/Transforms/Passes.h" #include @@ -92,6 +93,7 @@ inline void registerAllPasses() { arm_sme::registerArmSMEPasses(); arm_sve::registerArmSVEPasses(); emitc::registerEmitCPasses(); + xegpu::registerXeGPUPasses(); // Dialect pipelines bufferization::registerBufferizationPipelines(); diff --git a/mlir/lib/Dialect/XeGPU/CMakeLists.txt b/mlir/lib/Dialect/XeGPU/CMakeLists.txt index f33061b2d87c..9f57627c321f 100644 --- a/mlir/lib/Dialect/XeGPU/CMakeLists.txt +++ b/mlir/lib/Dialect/XeGPU/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(IR) +add_subdirectory(Transforms) diff --git a/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt b/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt new file mode 100644 index 000000000000..7fb64d3b97b8 --- /dev/null +++ b/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt @@ -0,0 +1,17 @@ +add_mlir_dialect_library(MLIRXeGPUTransforms + XeGPUFoldAliasOps.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/XeGPU + + DEPENDS + MLIRXeGPUPassIncGen + + LINK_LIBS PUBLIC + MLIRAffineUtils + MLIRIR + MLIRMemRefDialect + MLIRXeGPUDialect + MLIRPass + MLIRTransforms +) diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUFoldAliasOps.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUFoldAliasOps.cpp new file mode 100644 index 000000000000..9307e8eb784b --- /dev/null +++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUFoldAliasOps.cpp @@ -0,0 +1,82 @@ +//===- XeGPUFoldAliasOps.cpp - XeGPU alias ops folders ----------*- 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 "mlir/Dialect/XeGPU/Transforms/Passes.h" + +#include "mlir/Dialect/Affine/ViewLikeInterfaceUtils.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Dialect/XeGPU/IR/XeGPU.h" +#include "mlir/Dialect/XeGPU/Transforms/Transforms.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/Support/Debug.h" + +namespace mlir { +namespace xegpu { +#define GEN_PASS_DEF_XEGPUFOLDALIASOPS +#include "mlir/Dialect/XeGPU/Transforms/Passes.h.inc" +} // namespace xegpu +} // namespace mlir + +#define DEBUG_TYPE "xegpu-fold-alias-ops" +#define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE "]: ") + +using namespace mlir; + +namespace { +/// Merges subview operation with xegpu.create_nd_tdesc operation. +class XegpuCreateNdDescOpSubViewOpFolder final + : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(xegpu::CreateNdDescOp descOp, + PatternRewriter &rewriter) const override; +}; +} // namespace + +LogicalResult XegpuCreateNdDescOpSubViewOpFolder::matchAndRewrite( + xegpu::CreateNdDescOp descOp, PatternRewriter &rewriter) const { + auto subViewOp = descOp.getSource().getDefiningOp(); + + if (!subViewOp) + return rewriter.notifyMatchFailure(descOp, "not a subview producer"); + if (!subViewOp.hasUnitStride()) + return rewriter.notifyMatchFailure(descOp, "requires unit strides"); + + SmallVector resolvedOffsets; + affine::resolveIndicesIntoOpWithOffsetsAndStrides( + rewriter, descOp.getLoc(), subViewOp.getMixedOffsets(), + subViewOp.getMixedStrides(), subViewOp.getDroppedDims(), + descOp.getMixedOffsets(), resolvedOffsets); + + rewriter.replaceOpWithNewOp( + descOp, descOp.getTensorDesc().getType(), subViewOp.getSource(), + getAsOpFoldResult(resolvedOffsets)); + + return success(); +} + +void xegpu::populateXeGPUFoldAliasOpsPatterns(RewritePatternSet &patterns) { + patterns.add(patterns.getContext()); +} + +namespace { + +struct XeGPUFoldAliasOpsPass final + : public xegpu::impl::XeGPUFoldAliasOpsBase { + void runOnOperation() override; +}; + +} // namespace + +void XeGPUFoldAliasOpsPass::runOnOperation() { + RewritePatternSet patterns(&getContext()); + xegpu::populateXeGPUFoldAliasOpsPatterns(patterns); + (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns)); +} diff --git a/mlir/test/Dialect/XeGPU/xegpu-fold-alias-ops.mlir b/mlir/test/Dialect/XeGPU/xegpu-fold-alias-ops.mlir new file mode 100644 index 000000000000..d32954127fce --- /dev/null +++ b/mlir/test/Dialect/XeGPU/xegpu-fold-alias-ops.mlir @@ -0,0 +1,20 @@ +// RUN: mlir-opt -xegpu-fold-alias-ops -split-input-file %s | FileCheck %s + +func.func @fold_subview_with_xegpu_create_nd_tdesc(%arg0 : memref<256x256xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index) ->(!xegpu.tensor_desc<8x16xf32>) { + %subview = memref.subview %arg0[%arg1, %arg2] [32, 32] [1, 1] : + memref<256x256xf32> to memref<32x32xf32, strided<[256, 1], offset: ?>> + %0 = xegpu.create_nd_tdesc %subview[%arg3, %arg4] : + memref<32x32xf32, strided<[256, 1], offset: ?>> -> !xegpu.tensor_desc<8x16xf32> + return %0 : !xegpu.tensor_desc<8x16xf32> +} + +// CHECK-DAG: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1)> +// CHECK: func @fold_subview_with_xegpu_create_nd_tdesc +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: memref<256x256xf32> +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index +// CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index +// CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: index +// CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: index +// CHECK-DAG: %[[IDX0:.+]] = affine.apply #[[MAP]]()[%[[ARG1]], %[[ARG3]]] +// CHECK-DAG: %[[IDX1:.+]] = affine.apply #[[MAP]]()[%[[ARG2]], %[[ARG4]]] +// CHECK: xegpu.create_nd_tdesc %[[ARG0]][%[[IDX0]], %[[IDX1]]] : memref<256x256xf32> -> !xegpu.tensor_desc<8x16xf32> -- GitLab From b859a9fc152f83d657b1b59a99ede2478e285b27 Mon Sep 17 00:00:00 2001 From: Kojo Acquah Date: Fri, 19 Apr 2024 07:49:25 -0700 Subject: [PATCH 006/357] [mlir][ArmNeon] Update `LowerContractionToSMMLAPattern` to support proper unrolling for k dimension (#88591) Fixes correctness issue with current smmla unrolling patterns whereby unrolling K dimension would only include the result from the last tile along K. Updates patterns to feed previous smmla output of the previous tile into the next one along K. --- .../LowerContractionToSMMLAPattern.cpp | 20 ++- .../Dialect/ArmNeon/lower-to-arm-neon.mlir | 121 +++++++++++++++--- 2 files changed, 118 insertions(+), 23 deletions(-) diff --git a/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp b/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp index 7e390aa55197..3635cd319a07 100644 --- a/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp +++ b/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp @@ -133,6 +133,9 @@ public: smmlaShape.insert(smmlaShape.begin(), isVecmat ? 1 : 2); loopOrder.push_back(2); } + + // Keep track of the previous accumulator when tiling over K. + Value kAcc; for (SmallVector offsets : StaticTileOffsetRange(unrolledSize, smmlaShape, loopOrder)) { // Helper to compute the new shape of each operand and extract the slice. @@ -194,19 +197,26 @@ public: tiledRhs.getLoc(), collapsedInputType, tiledRhs); auto collapsedOutputType = VectorType::get(outputExpandedType.getNumElements(), accElementType); - auto collapsedRes = rewriter.createOrFold( - tiledAcc.getLoc(), collapsedOutputType, tiledAcc); + + bool initialKAcc = offsets.back() == 0; + Value collapsedRes; + if (!initialKAcc) { + collapsedRes = kAcc; + } else { + collapsedRes = rewriter.createOrFold( + tiledAcc.getLoc(), collapsedOutputType, tiledAcc); + } // Insert contract op - auto smmlaOp = rewriter.createOrFold( + kAcc = rewriter.createOrFold( op.getLoc(), collapsedRes.getType(), collapsedRes, collapsedLhs, collapsedRhs); // Reshape output back to 2D Value tiledRes = rewriter.createOrFold( - smmlaOp.getLoc(), tiledAcc.getType(), smmlaOp); + kAcc.getLoc(), tiledAcc.getType(), kAcc); - // With vecmat, only one row of tiled ACC can be inserted inot file result + // With vecmat, only one row of tiled ACC can be inserted into file result if (isVecmat) { tiledRes = rewriter.createOrFold(loc, tiledRes, 0); } diff --git a/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir b/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir index c276a5b0c2a1..297be91e7728 100644 --- a/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir +++ b/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt -test-lower-to-arm-neon -verify-diagnostics -split-input-file %s | FileCheck %s -// CHECK-LABEL: test_lower_vector_arm_neon_mixed_types +// CHECK-LABEL: vector_arm_neon_mixed_types // CHECK-SAME: %[[A0:.*]]: vector<2x8xi8>, %[[A1:.*]]: vector<2x8xi4>, %[[A2:.*]]: vector<2x2xi32> // CHECK-DAG: %[[D0:.*]] = arith.extsi %[[A1]] : vector<2x8xi4> to vector<2x8xi8> // CHECK-DAG: %[[D1:.*]] = vector.shape_cast %[[A0]] : vector<2x8xi8> to vector<16xi8> @@ -8,7 +8,7 @@ // CHECK-DAG: %[[D3:.*]] = vector.shape_cast %[[A2]] : vector<2x2xi32> to vector<4xi32> // CHECK-DAG: %[[D4:.*]] = arm_neon.intr.smmla %[[D3]], %[[D1]], %[[D2]] : vector<16xi8> to vector<4xi32> // CHECK-DAG: %[[D5:.*]] = vector.shape_cast %[[D4]] : vector<4xi32> to vector<2x2xi32> -func.func @test_lower_vector_arm_neon_mixed_types(%lhs: vector<2x8xi8>, %rhs: vector<2x8xi4>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { +func.func @vector_arm_neon_mixed_types(%lhs: vector<2x8xi8>, %rhs: vector<2x8xi4>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { %lhs_extsi = arith.extsi %lhs : vector<2x8xi8> to vector<2x8xi32> %rhs_extsi = arith.extsi %rhs : vector<2x8xi4> to vector<2x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<2x8xi32>, vector<2x8xi32> into vector<2x2xi32> @@ -17,14 +17,14 @@ func.func @test_lower_vector_arm_neon_mixed_types(%lhs: vector<2x8xi8>, %rhs: ve // ----- -// CHECK-LABEL: test_lower_vector_arm_neon_same_types +// CHECK-LABEL: vector_arm_neon_same_types // CHECK-SAME: %[[A0:.*]]: vector<2x8xi8>, %[[A1:.*]]: vector<2x8xi8>, %[[A2:.*]]: vector<2x2xi32> // CHECK-DAG: %[[D0:.*]] = vector.shape_cast %[[A0]] : vector<2x8xi8> to vector<16xi8> // CHECK-DAG: %[[D1:.*]] = vector.shape_cast %[[A1]] : vector<2x8xi8> to vector<16xi8> // CHECK-DAG: %[[D2:.*]] = vector.shape_cast %[[A2]] : vector<2x2xi32> to vector<4xi32> // CHECK-DAG: %[[D3:.*]] = arm_neon.intr.smmla %[[D2]], %[[D0]], %[[D1]] : vector<16xi8> to vector<4xi32> // CHECK-DAG: %[[D4:.*]] = vector.shape_cast %[[D3]] : vector<4xi32> to vector<2x2xi32> -func.func @test_lower_vector_arm_neon_same_types(%lhs: vector<2x8xi8>, %rhs: vector<2x8xi8>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { +func.func @vector_arm_neon_same_types(%lhs: vector<2x8xi8>, %rhs: vector<2x8xi8>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { %lhs_extsi = arith.extsi %lhs : vector<2x8xi8> to vector<2x8xi32> %rhs_extsi = arith.extsi %rhs : vector<2x8xi8> to vector<2x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<2x8xi32>, vector<2x8xi32> into vector<2x2xi32> @@ -33,17 +33,17 @@ func.func @test_lower_vector_arm_neon_same_types(%lhs: vector<2x8xi8>, %rhs: vec // ----- -// CHECK-LABEL: test_lower_vector_arm_neon_without_extsi +// CHECK-LABEL: vector_arm_neon_without_extsi // CHECK-SAME: %[[A0:.*]]: vector<2x8xi32>, %[[A1:.*]]: vector<2x8xi32>, %[[A2:.*]]: vector<2x2xi32> // CHECK-DAG: %[[D0:.*]] = vector.contract -func.func @test_lower_vector_arm_neon_without_extsi(%lhs: vector<2x8xi32>, %rhs: vector<2x8xi32>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { +func.func @vector_arm_neon_without_extsi(%lhs: vector<2x8xi32>, %rhs: vector<2x8xi32>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs, %rhs, %acc : vector<2x8xi32>, vector<2x8xi32> into vector<2x2xi32> return %res : vector<2x2xi32> } // ----- -// CHECK-LABEL: test_lower_vector_arm_neon_unroll +// CHECK-LABEL: vector_arm_neon_unroll // CHECK-SAME: %[[VAL_0:.*]]: vector<4x8xi8>, %[[VAL_1:.*]]: vector<4x8xi8>, %[[VAL_2:.*]]: vector<4x4xi32> // CHECK-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<4x4xi32> // CHECK-DAG: %[[VAL_4:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> @@ -84,7 +84,7 @@ func.func @test_lower_vector_arm_neon_without_extsi(%lhs: vector<2x8xi32>, %rhs: // CHECK-DAG: %[[VAL_39:.*]] = vector.insert_strided_slice %[[VAL_38]], %[[VAL_30]] {offsets = [2, 2], strides = [1, 1]} : vector<2x2xi32> into vector<4x4xi32> // CHECK-DAG: return %[[VAL_39]] : vector<4x4xi32> // CHECK-DAG: } -func.func @test_lower_vector_arm_neon_unroll(%lhs: vector<4x8xi8>, %rhs: vector<4x8xi8>, %acc : vector<4x4xi32>) -> vector<4x4xi32> { +func.func @vector_arm_neon_unroll(%lhs: vector<4x8xi8>, %rhs: vector<4x8xi8>, %acc : vector<4x4xi32>) -> vector<4x4xi32> { %lhs_extsi = arith.extsi %lhs : vector<4x8xi8> to vector<4x8xi32> %rhs_extsi = arith.extsi %rhs : vector<4x8xi8> to vector<4x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<4x8xi32>, vector<4x8xi32> into vector<4x4xi32> @@ -93,7 +93,7 @@ func.func @test_lower_vector_arm_neon_unroll(%lhs: vector<4x8xi8>, %rhs: vector< // ----- -// CHECK-LABEL: func.func @test_lower_vector_arm_neon_mixed_unroll( +// CHECK-LABEL: func.func @vector_arm_neon_mixed_unroll( // CHECK-SAME: %[[VAL_0:.*]]: vector<4x8xi8>, // CHECK-SAME: %[[VAL_1:.*]]: vector<2x8xi4>, // CHECK-SAME: %[[VAL_2:.*]]: vector<4x2xi32>) -> vector<4x2xi32> { @@ -117,7 +117,7 @@ func.func @test_lower_vector_arm_neon_unroll(%lhs: vector<4x8xi8>, %rhs: vector< // CHECK-DAG: %[[VAL_20:.*]] = vector.insert_strided_slice %[[VAL_19]], %[[VAL_12]] {offsets = [2, 0], strides = [1, 1]} : vector<2x2xi32> into vector<4x2xi32> // CHECK-DAG: return %[[VAL_20]] : vector<4x2xi32> // CHECK-DAG: } -func.func @test_lower_vector_arm_neon_mixed_unroll(%lhs: vector<4x8xi8>, %rhs: vector<2x8xi4>, %acc : vector<4x2xi32>) -> vector<4x2xi32> { +func.func @vector_arm_neon_mixed_unroll(%lhs: vector<4x8xi8>, %rhs: vector<2x8xi4>, %acc : vector<4x2xi32>) -> vector<4x2xi32> { %lhs_extsi = arith.extsi %lhs : vector<4x8xi8> to vector<4x8xi32> %rhs_extsi = arith.extsi %rhs : vector<2x8xi4> to vector<2x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<4x8xi32>, vector<2x8xi32> into vector<4x2xi32> @@ -126,9 +126,9 @@ func.func @test_lower_vector_arm_neon_mixed_unroll(%lhs: vector<4x8xi8>, %rhs: v // ----- -// CHECK-LABEL: func.func @test_lower_vector_arm_neon_unroll_incompatible_shape( +// CHECK-LABEL: func.func @vector_arm_neon_unroll_incompatible_shape( // CHECK-DAG: %[[result:.*]] = vector.contract -func.func @test_lower_vector_arm_neon_unroll_incompatible_shape(%lhs: vector<4x12xi8>, %rhs: vector<4x12xi8>, %acc : vector<4x4xi32>) -> vector<4x4xi32> { +func.func @vector_arm_neon_unroll_incompatible_shape(%lhs: vector<4x12xi8>, %rhs: vector<4x12xi8>, %acc : vector<4x4xi32>) -> vector<4x4xi32> { %lhs_extsi = arith.extsi %lhs : vector<4x12xi8> to vector<4x12xi32> %rhs_extsi = arith.extsi %rhs : vector<4x12xi8> to vector<4x12xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<4x12xi32>, vector<4x12xi32> into vector<4x4xi32> @@ -137,7 +137,7 @@ func.func @test_lower_vector_arm_neon_unroll_incompatible_shape(%lhs: vector<4x1 // ----- -// CHECK-LABEL: func.func @test_lower_vector_arm_neon_vecmat_unroll( +// CHECK-LABEL: func.func @vector_arm_neon_vecmat_unroll( // CHECK-SAME: %[[VAL_0:.*]]: vector<8xi8>, // CHECK-SAME: %[[VAL_1:.*]]: vector<8x8xi8>, // CHECK-SAME: %[[VAL_2:.*]]: vector<8xi32>) -> vector<8xi32> { @@ -190,7 +190,7 @@ func.func @test_lower_vector_arm_neon_unroll_incompatible_shape(%lhs: vector<4x1 // CHECK: %[[VAL_49:.*]] = vector.insert_strided_slice %[[VAL_48]], %[[VAL_38]] {offsets = [6], strides = [1]} : vector<2xi32> into vector<8xi32> // CHECK: return %[[VAL_49]] : vector<8xi32> // CHECK: } -func.func @test_lower_vector_arm_neon_vecmat_unroll(%lhs: vector<8xi8>, %rhs: vector<8x8xi8>, %acc : vector<8xi32>) -> vector<8xi32> { +func.func @vector_arm_neon_vecmat_unroll(%lhs: vector<8xi8>, %rhs: vector<8x8xi8>, %acc : vector<8xi32>) -> vector<8xi32> { %lhs_extsi= arith.extsi %lhs : vector<8xi8> to vector<8xi32> %rhs_extsi = arith.extsi %rhs : vector<8x8xi8> to vector<8x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1) -> (d1)>, affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0)>], iterator_types = ["parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<8xi32>, vector<8x8xi32> into vector<8xi32> @@ -199,7 +199,7 @@ func.func @test_lower_vector_arm_neon_vecmat_unroll(%lhs: vector<8xi8>, %rhs: ve // ----- -// CHECK-LABEL: func.func @test_lower_vector_arm_neon_vecmat_unroll_leading_dim( +// CHECK-LABEL: func.func @vector_arm_neon_vecmat_unroll_leading_dim( // CHECK-SAME: %[[VAL_0:.*]]: vector<1x8xi8>, // CHECK-SAME: %[[VAL_1:.*]]: vector<8x8xi8>, // CHECK-SAME: %[[VAL_2:.*]]: vector<1x8xi32>) -> vector<1x8xi32> { @@ -252,7 +252,7 @@ func.func @test_lower_vector_arm_neon_vecmat_unroll(%lhs: vector<8xi8>, %rhs: ve // CHECK: %[[VAL_49:.*]] = vector.insert_strided_slice %[[VAL_48]], %[[VAL_38]] {offsets = [0, 6], strides = [1]} : vector<2xi32> into vector<1x8xi32> // CHECK: return %[[VAL_49]] : vector<1x8xi32> // CHECK: } -func.func @test_lower_vector_arm_neon_vecmat_unroll_leading_dim(%lhs: vector<1x8xi8>, %rhs: vector<8x8xi8>, %acc : vector<1x8xi32>) -> vector<1x8xi32> { +func.func @vector_arm_neon_vecmat_unroll_leading_dim(%lhs: vector<1x8xi8>, %rhs: vector<8x8xi8>, %acc : vector<1x8xi32>) -> vector<1x8xi32> { %lhs_extsi= arith.extsi %lhs : vector<1x8xi8> to vector<1x8xi32> %rhs_extsi = arith.extsi %rhs : vector<8x8xi8> to vector<8x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<1x8xi32>, vector<8x8xi32> into vector<1x8xi32> @@ -261,11 +261,96 @@ func.func @test_lower_vector_arm_neon_vecmat_unroll_leading_dim(%lhs: vector<1x8 // ----- -// CHECK-LABEL: func.func @test_lower_vector_arm_neon_matvec +// CHECK-LABEL: func.func @vector_arm_neon_matvec // CHECK-NOT: arm_neon.intr.smmla -func.func @test_lower_vector_arm_neon_matvec(%lhs: vector<8x8xi8>, %rhs: vector<8xi8>, %acc : vector<8xi32>) -> vector<8xi32> { +func.func @vector_arm_neon_matvec(%lhs: vector<8x8xi8>, %rhs: vector<8xi8>, %acc : vector<8xi32>) -> vector<8xi32> { %rhs_extsi= arith.extsi %rhs : vector<8xi8> to vector<8xi32> %lhs_extsi = arith.extsi %lhs : vector<8x8xi8> to vector<8x8xi32> %res = vector.contract {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,affine_map<(d0, d1) -> (d1)>, affine_map<(d0, d1) -> (d0)>], iterator_types = ["parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<8x8xi32>, vector<8xi32> into vector<8xi32> return %res : vector<8xi32> } + + +// ----- + +// CHECK-LABEL: func.func @vector_arm_neon_k_unroll( +// CHECK-SAME: %[[VAL_0:.*]]: vector<2x16xi8>, +// CHECK-SAME: %[[VAL_1:.*]]: vector<2x16xi4>, +// CHECK-SAME: %[[VAL_2:.*]]: vector<2x2xi32>) -> vector<2x2xi32> { +// CHECK: %[[VAL_3:.*]] = arith.extsi %[[VAL_1]] : vector<2x16xi4> to vector<2x16xi8> +// CHECK: %[[VAL_4:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<2x16xi8> to vector<2x8xi8> +// CHECK: %[[VAL_5:.*]] = vector.extract_strided_slice %[[VAL_3]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<2x16xi8> to vector<2x8xi8> +// CHECK: %[[VAL_6:.*]] = vector.shape_cast %[[VAL_4]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_7:.*]] = vector.shape_cast %[[VAL_5]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_8:.*]] = vector.shape_cast %[[VAL_2]] : vector<2x2xi32> to vector<4xi32> +// CHECK: %[[KACC_0:.*]] = arm_neon.intr.smmla %[[VAL_8]], %[[VAL_6]], %[[VAL_7]] : vector<16xi8> to vector<4xi32> +// CHECK: %[[VAL_10:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 8], sizes = [2, 8], strides = [1, 1]} : vector<2x16xi8> to vector<2x8xi8> +// CHECK: %[[VAL_11:.*]] = vector.extract_strided_slice %[[VAL_3]] {offsets = [0, 8], sizes = [2, 8], strides = [1, 1]} : vector<2x16xi8> to vector<2x8xi8> +// CHECK: %[[VAL_12:.*]] = vector.shape_cast %[[VAL_10]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_13:.*]] = vector.shape_cast %[[VAL_11]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[KACC_1:.*]] = arm_neon.intr.smmla %[[KACC_0]], %[[VAL_12]], %[[VAL_13]] : vector<16xi8> to vector<4xi32> +// CHECK: %[[VAL_15:.*]] = vector.shape_cast %[[KACC_1]] : vector<4xi32> to vector<2x2xi32> +// CHECK: return %[[VAL_15]] : vector<2x2xi32> +// CHECK: } +func.func @vector_arm_neon_k_unroll(%lhs: vector<2x16xi8>, %rhs: vector<2x16xi4>, %acc : vector<2x2xi32>) -> vector<2x2xi32> { + %lhs_extsi = arith.extsi %lhs : vector<2x16xi8> to vector<2x16xi32> + %rhs_extsi = arith.extsi %rhs : vector<2x16xi4> to vector<2x16xi32> + %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<2x16xi32>, vector<2x16xi32> into vector<2x2xi32> + return %res : vector<2x2xi32> +} + +// ----- + +// CHECK-LABEL: func.func @vector_arm_neon_k_unroll_vecmat( +// CHECK-SAME: %[[VAL_0:.*]]: vector<1x32xi8>, +// CHECK-SAME: %[[VAL_1:.*]]: vector<2x32xi4>, +// CHECK-SAME: %[[VAL_2:.*]]: vector<1x2xi32>) -> vector<1x2xi32> { +// CHECK: %[[VAL_3:.*]] = arith.constant dense<0> : vector<2x2xi32> +// CHECK: %[[VAL_4:.*]] = arith.constant dense<0> : vector<2x8xi8> +// CHECK: %[[VAL_5:.*]] = arith.constant dense<0> : vector<1x2xi32> +// CHECK: %[[VAL_6:.*]] = arith.extsi %[[VAL_1]] : vector<2x32xi4> to vector<2x32xi8> +// CHECK: %[[VAL_7:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 0], sizes = [1, 8], strides = [1, 1]} : vector<1x32xi8> to vector<1x8xi8> +// CHECK: %[[VAL_8:.*]] = vector.extract_strided_slice %[[VAL_6]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<2x32xi8> to vector<2x8xi8> +// CHECK: %[[VAL_9:.*]] = vector.insert_strided_slice %[[VAL_7]], %[[VAL_4]] {offsets = [0, 0], strides = [1, 1]} : vector<1x8xi8> into vector<2x8xi8> +// CHECK: %[[VAL_10:.*]] = vector.insert_strided_slice %[[VAL_2]], %[[VAL_3]] {offsets = [0, 0], strides = [1, 1]} : vector<1x2xi32> into vector<2x2xi32> +// CHECK: %[[VAL_11:.*]] = vector.shape_cast %[[VAL_9]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_12:.*]] = vector.shape_cast %[[VAL_8]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_13:.*]] = vector.shape_cast %[[VAL_10]] : vector<2x2xi32> to vector<4xi32> +// CHECK: %[[KACC_0:.*]] = arm_neon.intr.smmla %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : vector<16xi8> to vector<4xi32> +// CHECK: %[[VAL_15:.*]] = vector.shape_cast %[[KACC_0]] : vector<4xi32> to vector<2x2xi32> +// CHECK: %[[VAL_16:.*]] = vector.extract %[[VAL_15]][0] : vector<2xi32> from vector<2x2xi32> +// CHECK: %[[VAL_17:.*]] = vector.insert_strided_slice %[[VAL_16]], %[[VAL_5]] {offsets = [0, 0], strides = [1]} : vector<2xi32> into vector<1x2xi32> +// CHECK: %[[VAL_18:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 8], sizes = [1, 8], strides = [1, 1]} : vector<1x32xi8> to vector<1x8xi8> +// CHECK: %[[VAL_19:.*]] = vector.extract_strided_slice %[[VAL_6]] {offsets = [0, 8], sizes = [2, 8], strides = [1, 1]} : vector<2x32xi8> to vector<2x8xi8> +// CHECK: %[[VAL_20:.*]] = vector.insert_strided_slice %[[VAL_18]], %[[VAL_4]] {offsets = [0, 0], strides = [1, 1]} : vector<1x8xi8> into vector<2x8xi8> +// CHECK: %[[VAL_21:.*]] = vector.shape_cast %[[VAL_20]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_22:.*]] = vector.shape_cast %[[VAL_19]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[KACC_1:.*]] = arm_neon.intr.smmla %[[KACC_0]], %[[VAL_21]], %[[VAL_22]] : vector<16xi8> to vector<4xi32> +// CHECK: %[[VAL_24:.*]] = vector.shape_cast %[[KACC_1]] : vector<4xi32> to vector<2x2xi32> +// CHECK: %[[VAL_25:.*]] = vector.extract %[[VAL_24]][0] : vector<2xi32> from vector<2x2xi32> +// CHECK: %[[VAL_26:.*]] = vector.insert_strided_slice %[[VAL_25]], %[[VAL_17]] {offsets = [0, 0], strides = [1]} : vector<2xi32> into vector<1x2xi32> +// CHECK: %[[VAL_27:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 16], sizes = [1, 8], strides = [1, 1]} : vector<1x32xi8> to vector<1x8xi8> +// CHECK: %[[VAL_28:.*]] = vector.extract_strided_slice %[[VAL_6]] {offsets = [0, 16], sizes = [2, 8], strides = [1, 1]} : vector<2x32xi8> to vector<2x8xi8> +// CHECK: %[[VAL_29:.*]] = vector.insert_strided_slice %[[VAL_27]], %[[VAL_4]] {offsets = [0, 0], strides = [1, 1]} : vector<1x8xi8> into vector<2x8xi8> +// CHECK: %[[VAL_30:.*]] = vector.shape_cast %[[VAL_29]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_31:.*]] = vector.shape_cast %[[VAL_28]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[KACC_2:.*]] = arm_neon.intr.smmla %[[KACC_1]], %[[VAL_30]], %[[VAL_31]] : vector<16xi8> to vector<4xi32> +// CHECK: %[[VAL_33:.*]] = vector.shape_cast %[[KACC_2]] : vector<4xi32> to vector<2x2xi32> +// CHECK: %[[VAL_34:.*]] = vector.extract %[[VAL_33]][0] : vector<2xi32> from vector<2x2xi32> +// CHECK: %[[VAL_35:.*]] = vector.insert_strided_slice %[[VAL_34]], %[[VAL_26]] {offsets = [0, 0], strides = [1]} : vector<2xi32> into vector<1x2xi32> +// CHECK: %[[VAL_36:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 24], sizes = [1, 8], strides = [1, 1]} : vector<1x32xi8> to vector<1x8xi8> +// CHECK: %[[VAL_37:.*]] = vector.extract_strided_slice %[[VAL_6]] {offsets = [0, 24], sizes = [2, 8], strides = [1, 1]} : vector<2x32xi8> to vector<2x8xi8> +// CHECK: %[[VAL_38:.*]] = vector.insert_strided_slice %[[VAL_36]], %[[VAL_4]] {offsets = [0, 0], strides = [1, 1]} : vector<1x8xi8> into vector<2x8xi8> +// CHECK: %[[VAL_39:.*]] = vector.shape_cast %[[VAL_38]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[VAL_40:.*]] = vector.shape_cast %[[VAL_37]] : vector<2x8xi8> to vector<16xi8> +// CHECK: %[[KACC_3:.*]] = arm_neon.intr.smmla %[[KACC_2]], %[[VAL_39]], %[[VAL_40]] : vector<16xi8> to vector<4xi32> +// CHECK: %[[VAL_42:.*]] = vector.shape_cast %[[KACC_3]] : vector<4xi32> to vector<2x2xi32> +// CHECK: %[[VAL_43:.*]] = vector.extract %[[VAL_42]][0] : vector<2xi32> from vector<2x2xi32> +// CHECK: %[[VAL_44:.*]] = vector.insert_strided_slice %[[VAL_43]], %[[VAL_35]] {offsets = [0, 0], strides = [1]} : vector<2xi32> into vector<1x2xi32> +// CHECK: return %[[VAL_44]] : vector<1x2xi32> +func.func @vector_arm_neon_k_unroll_vecmat(%lhs: vector<1x32xi8>, %rhs: vector<2x32xi4>, %acc : vector<1x2xi32>) -> vector<1x2xi32> { + %lhs_extsi = arith.extsi %lhs : vector<1x32xi8> to vector<1x32xi32> + %rhs_extsi = arith.extsi %rhs : vector<2x32xi4> to vector<2x32xi32> + %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind} %lhs_extsi, %rhs_extsi, %acc : vector<1x32xi32>, vector<2x32xi32> into vector<1x2xi32> + return %res : vector<1x2xi32> +} -- GitLab From 3a4bc11b675c0511319c2843221133e986825b3b Mon Sep 17 00:00:00 2001 From: Dinar Temirbulatov Date: Fri, 19 Apr 2024 14:48:39 +0000 Subject: [PATCH 007/357] Reapply "[Clang][AArch64] Warn when calling non/streaming about vector size difference (#79842)" This reverts commit 950bb097e11d6ee26533c00519c62df994322228 --- clang/include/clang/Basic/DiagnosticGroups.td | 3 + .../clang/Basic/DiagnosticSemaKinds.td | 10 ++ clang/lib/Sema/SemaChecking.cpp | 22 ++- clang/lib/Sema/SemaDecl.cpp | 12 +- .../Sema/aarch64-incompat-sm-builtin-calls.c | 6 +- clang/test/Sema/aarch64-sme-func-attrs.c | 136 +++++++++++++++++- 6 files changed, 184 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 5251774ff4ef..47747d8704b6 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1412,6 +1412,9 @@ def MultiGPU: DiagGroup<"multi-gpu">; // libc and the CRT to be skipped. def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">; +// A warning group related to AArch64 SME function attribues. +def AArch64SMEAttributes : DiagGroup<"aarch64-sme-attributes">; + // A warning group for things that will change semantics in the future. def FutureCompat : DiagGroup<"future-compat">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a2d8bf4e4eb..1bbe76ff6bd2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3754,6 +3754,16 @@ def err_sme_definition_using_za_in_non_sme_target : Error< "function using ZA state requires 'sme'">; def err_sme_definition_using_zt0_in_non_sme2_target : Error< "function using ZT0 state requires 'sme2'">; +def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning< + "passing a VL-dependent argument to/from a function that has a different" + " streaming-mode. The streaming and non-streaming vector lengths may be" + " different">, + InGroup, DefaultIgnore; +def warn_sme_locally_streaming_has_vl_args_returns : Warning< + "passing/returning a VL-dependent argument to/from a __arm_locally_streaming" + " function. The streaming and non-streaming vector" + " lengths may be different">, + InGroup, DefaultIgnore; def err_conflicting_attributes_arm_state : Error< "conflicting attributes for state '%0'">; def err_sme_streaming_cannot_be_multiversioned : Error< diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 73e76e05a0d9..2ef95741b3d6 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7953,6 +7953,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, // For variadic functions, we may have more args than parameters. // For some K&R functions, we may have less args than parameters. const auto N = std::min(Proto->getNumParams(), Args.size()); + bool AnyScalableArgsOrRet = Proto->getReturnType()->isSizelessVectorType(); for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. if (const Expr *Arg = Args[ArgIdx]) { @@ -7966,6 +7967,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, checkAIXMemberAlignment((Arg->getExprLoc()), Arg); QualType ParamTy = Proto->getParamType(ArgIdx); + if (ParamTy->isSizelessVectorType()) + AnyScalableArgsOrRet = true; QualType ArgTy = Arg->getType(); CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1), ArgTy, ParamTy); @@ -7986,6 +7989,23 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } } + // If the call requires a streaming-mode change and has scalable vector + // arguments or return values, then warn the user that the streaming and + // non-streaming vector lengths may be different. + const auto *CallerFD = dyn_cast(CurContext); + if (CallerFD && (!FD || !FD->getBuiltinID()) && AnyScalableArgsOrRet) { + bool IsCalleeStreaming = + ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask; + bool IsCalleeStreamingCompatible = + ExtInfo.AArch64SMEAttributes & + FunctionType::SME_PStateSMCompatibleMask; + ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD); + if (!IsCalleeStreamingCompatible && + (CallerFnType == ArmStreamingCompatible || + ((CallerFnType == ArmStreaming) ^ IsCalleeStreaming))) + Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming); + } + FunctionType::ArmStateValue CalleeArmZAState = FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes); FunctionType::ArmStateValue CalleeArmZT0State = @@ -7994,7 +8014,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, CalleeArmZT0State != FunctionType::ARM_None) { bool CallerHasZAState = false; bool CallerHasZT0State = false; - if (const auto *CallerFD = dyn_cast(CurContext)) { + if (CallerFD) { auto *Attr = CallerFD->getAttr(); if (Attr && Attr->isNewZA()) CallerHasZAState = true; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index af6b3f21f15a..5fed554d9e25 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12408,12 +12408,22 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } // Check if the function definition uses any AArch64 SME features without - // having the '+sme' feature enabled. + // having the '+sme' feature enabled and warn user if sme locally streaming + // function returns or uses arguments with VL-based types. if (DeclIsDefn) { const auto *Attr = NewFD->getAttr(); bool UsesSM = NewFD->hasAttr(); bool UsesZA = Attr && Attr->isNewZA(); bool UsesZT0 = Attr && Attr->isNewZT0(); + + if (NewFD->hasAttr()) { + if (NewFD->getReturnType()->isSizelessVectorType() || + llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) { + return P->getOriginalType()->isSizelessVectorType(); + })) + Diag(NewFD->getLocation(), + diag::warn_sme_locally_streaming_has_vl_args_returns); + } if (const auto *FPT = NewFD->getType()->getAs()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); UsesSM |= diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c index 55c97c73e8b6..6a1feeb9bf53 100644 --- a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c +++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ -// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s +// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -Waarch64-sme-attributes -fsyntax-only -verify %s // REQUIRES: aarch64-registered-target @@ -33,6 +33,7 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b); @@ -48,6 +49,7 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) { // expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}} return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b); @@ -68,6 +70,7 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_ return svadd_n_f64_m(pg, a, b); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) { // expected-no-warning return svadd_n_f64_m(pg, a, b); @@ -83,6 +86,7 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming { return svmul_lane_s16(op1, op2, 0); } +// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} __arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) { // expected-no-warning return svmul_lane_s16(op1, op2, 0); diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index bfc8768c3f36..12de16509ccb 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify=expected-cpp -x c++ %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s // Valid attributes @@ -496,3 +496,135 @@ void fmv_caller() { just_fine(); incompatible_locally_streaming(); } + +void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { } + +__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; } + +void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { } + +__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible { __SVInt8_t r; return r; } + +void sme_no_streaming_with_vl_arg(__SVInt8_t a) { } + +__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; } + +// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +__arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { } + +// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}} +__arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; } + +void sme_no_streaming_calling_streaming_with_vl_args() { + __SVInt8_t a; + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_streaming_with_vl_arg(a); +} + +void sme_no_streaming_calling_streaming_with_return_vl() { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming { + __SVInt8_t a; + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_no_streaming_with_vl_arg(a); +} + +void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sc(arg); +} + +__SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + return s(); +} + +void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_streaming_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + sme_no_streaming_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible { + // expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + // expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}} + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_streaming_calling_streaming(__SVInt8_t arg, void (*s)( __SVInt8_t arg) __arm_streaming) __arm_streaming { + s(arg); +} + +__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*s)(void) __arm_streaming) __arm_streaming { + return s(); +} + +void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming { + sme_streaming_with_vl_arg(a); +} + +void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming { + __SVInt8_t r = sme_streaming_returns_vl(); +} + +void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm_streaming { + sme_streaming_compatible_with_vl_arg(a); +} + +void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} + +void sme_no_streaming_calling_streaming_compatible_with_vl_args() { + __SVInt8_t a; + sme_streaming_compatible_with_vl_arg(a); +} + +void sme_no_streaming_calling_streaming_compatible_with_return_vl() { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} + +void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() { + __SVInt8_t a; + sme_no_streaming_with_vl_arg(a); +} + +void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() { + __SVInt8_t r = sme_no_streaming_returns_vl(); +} + +void sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible { + sme_streaming_compatible_with_vl_arg(arg); +} + +void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible { + __SVInt8_t r = sme_streaming_compatible_returns_vl(); +} -- GitLab From 97c71247312c7e5261168283c13cd7e3ecd039a5 Mon Sep 17 00:00:00 2001 From: ZelinMa557 <72912470+ZelinMa557@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:59:07 +0800 Subject: [PATCH 008/357] [InstCombine] Regard zext nneg as sext when folding add(zext neg(add)) (#88887) fixes #88348 proof: https://alive2.llvm.org/ce/z/fJnM7t test will be added later --------- Signed-off-by: ZelinMa557 <3388706467@qq.com> --- .../InstCombine/InstCombineAddSub.cpp | 6 +-- llvm/test/Transforms/InstCombine/add.ll | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 9a16ca96db76..fc284bc61cce 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -828,9 +828,10 @@ static Instruction *foldNoWrapAdd(BinaryOperator &Add, // More general combining of constants in the wide type. // (sext (X +nsw NarrowC)) + C --> (sext X) + (sext(NarrowC) + C) + // or (zext nneg (X +nsw NarrowC)) + C --> (sext X) + (sext(NarrowC) + C) Constant *NarrowC; - if (match(Op0, - m_OneUse(m_SExt(m_NSWAddLike(m_Value(X), m_Constant(NarrowC)))))) { + if (match(Op0, m_OneUse(m_SExtLike( + m_NSWAddLike(m_Value(X), m_Constant(NarrowC)))))) { Value *WideC = Builder.CreateSExt(NarrowC, Ty); Value *NewC = Builder.CreateAdd(WideC, Op1C); Value *WideX = Builder.CreateSExt(X, Ty); @@ -844,7 +845,6 @@ static Instruction *foldNoWrapAdd(BinaryOperator &Add, Value *WideX = Builder.CreateZExt(X, Ty); return BinaryOperator::CreateAdd(WideX, NewC); } - return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll index 39b4ad805508..56ee54d351e7 100644 --- a/llvm/test/Transforms/InstCombine/add.ll +++ b/llvm/test/Transforms/InstCombine/add.ll @@ -4091,6 +4091,43 @@ define i32 @fold_zext_addition_fail2(i8 %x) { ret i32 %r } +define i32 @fold_zext_nneg_add_const(i8 %x) { +; CHECK-LABEL: @fold_zext_nneg_add_const( +; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[TMP1]], 98 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = add nsw i8 %x, 123 + %ze = zext nneg i8 %xx to i32 + %r = add nsw i32 %ze, -25 + ret i32 %r +} + +define i32 @fold_zext_nneg_add_const_fail1(i8 %x) { +; CHECK-LABEL: @fold_zext_nneg_add_const_fail1( +; CHECK-NEXT: [[XX:%.*]] = add nsw i8 [[X:%.*]], 123 +; CHECK-NEXT: [[ZE:%.*]] = zext i8 [[XX]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[ZE]], -25 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = add nsw i8 %x, 123 + %ze = zext i8 %xx to i32 + %r = add nsw i32 %ze, -25 + ret i32 %r +} + +define i32 @fold_zext_nneg_add_const_fail2(i8 %x) { +; CHECK-LABEL: @fold_zext_nneg_add_const_fail2( +; CHECK-NEXT: [[XX:%.*]] = add i8 [[X:%.*]], 123 +; CHECK-NEXT: [[ZE:%.*]] = zext nneg i8 [[XX]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[ZE]], -25 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = add i8 %x, 123 + %ze = zext nneg i8 %xx to i32 + %r = add nsw i32 %ze, -25 + ret i32 %r +} declare void @llvm.assume(i1) declare void @fake_func(i32) -- GitLab From f76475c026acbc30ef42834b3956bfa7bd61052b Mon Sep 17 00:00:00 2001 From: Christian Ulmann Date: Fri, 19 Apr 2024 17:12:22 +0200 Subject: [PATCH 009/357] [MLIR][LLVM] Add vector exception to composite type element ignore mode (#89385) This commit fixes a bug in the DICompositeType element ignore mode. It seems that vectors require the presence of elements, as they otherwise do not pass the verifier. --- mlir/lib/Target/LLVMIR/DebugImporter.cpp | 5 +++- .../Import/ignore-composite-type-elements.ll | 24 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp index b4c0115b0bca..1ab55b079b52 100644 --- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp @@ -71,7 +71,10 @@ DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) { DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) { std::optional flags = symbolizeDIFlags(node->getFlags()); SmallVector elements; - if (!dropDICompositeTypeElements) { + + // A vector always requires an element. + bool isVectorType = flags && bitEnumContainsAll(*flags, DIFlags::Vector); + if (isVectorType || !dropDICompositeTypeElements) { for (llvm::DINode *element : node->getElements()) { assert(element && "expected a non-null element type"); elements.push_back(translate(element)); diff --git a/mlir/test/Target/LLVMIR/Import/ignore-composite-type-elements.ll b/mlir/test/Target/LLVMIR/Import/ignore-composite-type-elements.ll index a249f2290d7a..d92d07085610 100644 --- a/mlir/test/Target/LLVMIR/Import/ignore-composite-type-elements.ll +++ b/mlir/test/Target/LLVMIR/Import/ignore-composite-type-elements.ll @@ -1,4 +1,4 @@ -; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -split-input-file -drop-di-composite-type-elements %s | FileCheck %s +; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -split-input-file -drop-di-composite-type-elements -split-input-file %s | FileCheck %s ; Verifies that the according flag avoids the conversion of the elements of the ; DICompositeType. @@ -23,3 +23,25 @@ define void @composite_type() !dbg !3 { !7 = !{!9} !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, flags: DIFlagArtificial | DIFlagObjectPointer) !9 = !DIDerivedType(tag: DW_TAG_member, name: "call_field", file: !2, baseType: !8) + +; // ----- + +; CHECK: #{{.+}} = #llvm.di_composite_type + +define void @composite_type() !dbg !3 { + ret void +} + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) +!2 = !DIFile(filename: "debug-info.ll", directory: "/") +!3 = distinct !DISubprogram(name: "composite_type", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1, type: !4) +!4 = !DISubroutineType(types: !5) +!5 = !{!7} +!6 = !DIBasicType(name: "int") +!7 = !DICompositeType(tag: DW_TAG_array_type, name: "vector", flags: DIFlagVector, elements: !8, baseType: !6) +!8 = !{!9} +!9 = !DISubrange(count: 4) -- GitLab From 9dbf3e2384e450c2b4f282b85b9ec47c65976194 Mon Sep 17 00:00:00 2001 From: Sergio Afonso Date: Fri, 19 Apr 2024 16:13:10 +0100 Subject: [PATCH 010/357] [Flang][OpenMP] NFC: Simplify handling of insertion points (#89221) This patch replaces some `saveInsertionPoint`, `restoreInsertionPoint` call pairs for an `InsertionGuard` instance where it makes sense within Flang OpenMP lowering to make further modifications less error-prone. --- flang/lib/Lower/OpenMP/DataSharingProcessor.cpp | 11 ++++------- flang/lib/Lower/OpenMP/OpenMP.cpp | 4 +--- flang/lib/Lower/OpenMP/ReductionProcessor.cpp | 3 +-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 5a42e6a6aa41..8bb2f83282b5 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -136,7 +136,7 @@ void DataSharingProcessor::insertBarrier() { void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { bool cmpCreated = false; - mlir::OpBuilder::InsertPoint localInsPt = firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); for (const omp::Clause &clause : clauses) { if (clause.id != llvm::omp::OMPC_lastprivate) continue; @@ -203,12 +203,11 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { // Lastprivate operation is inserted at the end // of the lexically last section in the sections // construct - mlir::OpBuilder::InsertPoint unstructuredSectionsIP = - firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard unstructuredSectionsGuard( + firOpBuilder); mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); firOpBuilder.setInsertionPoint(lastOper); lastPrivIP = firOpBuilder.saveInsertionPoint(); - firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP); } } } else if (mlir::isa(op)) { @@ -268,7 +267,6 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { "simd/worksharing-loop"); } } - firOpBuilder.restoreInsertionPoint(localInsPt); } void DataSharingProcessor::collectSymbols( @@ -372,7 +370,7 @@ void DataSharingProcessor::doPrivatize( uniquePrivatizerName)) return existingPrivatizer; - auto ip = firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); firOpBuilder.setInsertionPoint(&moduleOp.getBodyRegion().front(), moduleOp.getBodyRegion().front().begin()); auto result = firOpBuilder.create( @@ -424,7 +422,6 @@ void DataSharingProcessor::doPrivatize( } symTable->popScope(); - firOpBuilder.restoreInsertionPoint(ip); return result; }(); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 4424788e0132..db99617a7ba9 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -134,7 +134,7 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); - mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(firOpBuilder); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); // If the symbol corresponds to the original ThreadprivateOp, use the symbol @@ -197,8 +197,6 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, getExtendedValue(sexv, symThreadprivateValue); converter.bindSymbol(*sym, symThreadprivateExv); } - - firOpBuilder.restoreInsertionPoint(insPt); } static mlir::Operation * diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index f42386fe2736..6a91ee4b32f6 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -486,9 +486,8 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, assert(cstNeedsDealloc.has_value() && "createTempFromMold decides this statically"); if (cstNeedsDealloc.has_value() && *cstNeedsDealloc != false) { - auto insPt = builder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(builder); createReductionCleanupRegion(builder, loc, reductionDecl); - builder.restoreInsertionPoint(insPt); } // Put the temporary inside of a box: -- GitLab From 5e5b8c49096afba8e4e0fd094a5ab905a9acced0 Mon Sep 17 00:00:00 2001 From: Sergio Afonso Date: Fri, 19 Apr 2024 16:15:10 +0100 Subject: [PATCH 011/357] [MLIR][OpenMP] Verify loop wrapper properties of omp.parallel (#88722) This patch extends verification of the `omp.parallel` operation to check it is correctly defined when taking a loop wrapper role. In OpenMP, a PARALLEL construct can be either a (potenially combined) block construct or a loop construct, when appearing as part of a composite construct. This is currently the case for the DISTRIBUTE PARALLEL DO/FOR and DISTRIBUTE PARALLEL DO/FOR SIMD exclusively. When used to represent the PARALLEL leaf of a composite construct, it must follow the rules of a wrapper loop operation in MLIR, and this is what this patch ensures. No additional restrictions are introduced for PARALLEL block constructs. --- mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 16 ++++++ mlir/test/Dialect/OpenMP/invalid.mlir | 52 ++++++++++++++++++++ mlir/test/Dialect/OpenMP/ops.mlir | 20 +++++++- 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index f380926c4bce..528a0d05b101 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -1344,6 +1344,22 @@ static LogicalResult verifyPrivateVarList(OpType &op) { } LogicalResult ParallelOp::verify() { + // Check that it is a valid loop wrapper if it's taking that role. + if (isa((*this)->getParentOp())) { + if (!isWrapper()) + return emitOpError() << "must take a loop wrapper role if nested inside " + "of 'omp.distribute'"; + + if (LoopWrapperInterface nested = getNestedWrapper()) { + // Check for the allowed leaf constructs that may appear in a composite + // construct directly after PARALLEL. + if (!isa(nested)) + return emitError() << "only supported nested wrapper is 'omp.wsloop'"; + } else { + return emitOpError() << "must not wrap an 'omp.loop_nest' directly"; + } + } + if (getAllocateVars().size() != getAllocatorsVars().size()) return emitError( "expected equal sizes for allocate and allocator variables"); diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index 1f04f4570687..2f24dce4233e 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -10,6 +10,58 @@ func.func @unknown_clause() { // ----- +func.func @not_wrapper() { + omp.distribute { + // expected-error@+1 {{op must take a loop wrapper role if nested inside of 'omp.distribute'}} + omp.parallel { + %0 = arith.constant 0 : i32 + omp.terminator + } + omp.terminator + } + + return +} + +// ----- + +func.func @invalid_nested_wrapper(%lb : index, %ub : index, %step : index) { + omp.distribute { + // expected-error@+1 {{only supported nested wrapper is 'omp.wsloop'}} + omp.parallel { + omp.simd { + omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) { + omp.yield + } + omp.terminator + } + omp.terminator + } + omp.terminator + } + + return +} + +// ----- + +func.func @no_nested_wrapper(%lb : index, %ub : index, %step : index) { + omp.distribute { + // expected-error@+1 {{op must not wrap an 'omp.loop_nest' directly}} + omp.parallel { + omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) { + omp.yield + } + omp.terminator + } + omp.terminator + } + + return +} + +// ----- + func.func @if_once(%n : i1) { // expected-error@+1 {{`if` clause can appear at most once in the expansion of the oilist directive}} omp.parallel if(%n : i1) if(%n : i1) { diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index e2ca12afc14b..c10fc88211c3 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -51,7 +51,7 @@ func.func @omp_terminator() -> () { omp.terminator } -func.func @omp_parallel(%data_var : memref, %if_cond : i1, %num_threads : i32) -> () { +func.func @omp_parallel(%data_var : memref, %if_cond : i1, %num_threads : i32, %idx : index) -> () { // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref -> %{{.*}} : memref) "omp.parallel" (%if_cond, %num_threads, %data_var, %data_var) ({ @@ -85,6 +85,24 @@ func.func @omp_parallel(%data_var : memref, %if_cond : i1, %num_threads : i omp.terminator }) {operandSegmentSizes = array} : (memref, memref) -> () + // CHECK: omp.distribute + omp.distribute { + // CHECK-NEXT: omp.parallel + omp.parallel { + // CHECK-NEXT: omp.wsloop + // TODO Remove induction variables from omp.wsloop. + omp.wsloop for (%iv) : index = (%idx) to (%idx) step (%idx) { + // CHECK-NEXT: omp.loop_nest + omp.loop_nest (%iv2) : index = (%idx) to (%idx) step (%idx) { + omp.yield + } + omp.terminator + } + omp.terminator + } + omp.terminator + } + return } -- GitLab From 64cc3fad53c8313ad2fb3f2ba2fd44f280e5babf Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Fri, 19 Apr 2024 17:44:12 +0200 Subject: [PATCH 012/357] [Clang] Fix the mangling of lambdas (#89204) Lambdas used in the initializer of a local class were not mangling the name of the member. Fixes #88906 --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Basic/LangOptions.h | 5 ++ clang/lib/AST/ItaniumMangle.cpp | 18 ++++---- clang/lib/Frontend/CompilerInvocation.cpp | 5 ++ .../CodeGenCXX/mangle-lambdas-gh88906.cpp | 46 +++++++++++++++++++ 5 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e0a6d2f0fc7c..aea8fda35bb2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -549,6 +549,7 @@ Bug Fixes to C++ Support - Fix a crash in requires expression with templated base class member function. Fixes (#GH84020). - Fix a crash caused by defined struct in a type alias template when the structure has fields with dependent type. Fixes (#GH75221). +- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 24b109e32cdd..75562284ec7d 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -224,6 +224,11 @@ public: /// - the parameter list of a template template parameter Ver17, + /// Attempt to be ABI-compatible with code generated by Clang 18.0.x. + /// This causes clang to revert some fixes to the mangling of lambdas + /// in the initializers of members of local classes. + Ver18, + /// Conform to the underlying platform's C and C++ ABIs as closely /// as we can. Latest diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c3b98d2d2149..106c69dd5bee 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1062,26 +1062,23 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // ::= // const DeclContext *DC = Context.getEffectiveDeclContext(ND); + bool IsLambda = isLambda(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. // FIXME: This is a hack; extern variables declared locally should have // a proper semantic declaration context! - if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) + if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = Context.getEffectiveParentContext(DC); - else if (GetLocalClassDecl(ND)) { + else if (GetLocalClassDecl(ND) && + (!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) { mangleLocalName(GD, AdditionalAbiTags); return; } assert(!isa(DC) && "context cannot be LinkageSpecDecl"); - if (isLocalContainerContext(DC)) { - mangleLocalName(GD, AdditionalAbiTags); - return; - } - // Closures can require a nested-name mangling even if they're semantically // in the global namespace. if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { @@ -1089,6 +1086,11 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, return; } + if (isLocalContainerContext(DC)) { + mangleLocalName(GD, AdditionalAbiTags); + return; + } + if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; @@ -2201,8 +2203,6 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (NoFunction && isLocalContainerContext(DC)) return; - assert(!isLocalContainerContext(DC)); - const NamedDecl *ND = cast(DC); if (mangleSubstitution(ND)) return; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5531e938e0f4..8236051e30c4 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3660,6 +3660,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, case LangOptions::ClangABI::Ver17: GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0"); break; + case LangOptions::ClangABI::Ver18: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0"); + break; case LangOptions::ClangABI::Latest: break; } @@ -4167,6 +4170,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.setClangABICompat(LangOptions::ClangABI::Ver15); else if (Major <= 17) Opts.setClangABICompat(LangOptions::ClangABI::Ver17); + else if (Major <= 18) + Opts.setClangABICompat(LangOptions::ClangABI::Ver18); } else if (Ver != "latest") { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); diff --git a/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp new file mode 100644 index 000000000000..e7592cec5da7 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -emit-llvm -mconstructor-aliases -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fclang-abi-compat=18 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=CLANG18 %s +// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=MSABI %s + + +class func { +public: + template + func(T){}; + template + func(T, U){}; +}; + +void GH88906(){ + class Test{ + public: + func a{[]{ }, []{ }}; + func b{[]{ }}; + func c{[]{ }}; + } test; +} + +// CHECK-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev +// CHECK: call void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_ +// CHECK: call void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_ +// CHECK: call void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_ + +// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_ +// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_ +// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_ + +// CLANG18-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev +// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EZ7GH88906vENS1_UlvE0_EEET_T0_ +// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_ +// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_ + + + +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??0Test@?1??GH88906@@YAXXZ@QAE@XZ" +// MSABI: call x86_thiscallcc noundef ptr @"??$?0V@a@Test@?1??GH88906@@YAXXZ@V@12?1??3@YAXXZ@@func@@QAE@V@a@Test@?1??GH88906@@YAXXZ@V@23?1??4@YAXXZ@@Z" +// MSABI: call x86_thiscallcc noundef ptr @"??$?0V@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@b@Test@?1??GH88906@@YAXXZ@@Z" +// MSABI: call x86_thiscallcc noundef ptr @"??$?0V@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@c@Test@?1??GH88906@@YAXXZ@@Z" + +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V@a@Test@?1??GH88906@@YAXXZ@V@12?1??3@YAXXZ@@func@@QAE@V@a@Test@?1??GH88906@@YAXXZ@V@23?1??4@YAXXZ@@Z" +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@b@Test@?1??GH88906@@YAXXZ@@Z" +// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V@c@Test@?1??GH88906@@YAXXZ@@Z" -- GitLab From 26a59bf6fcfe3717d41ae6a92b8e0d3913c3fc1f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 19 Apr 2024 16:56:53 +0100 Subject: [PATCH 013/357] [TableGen] MacroFusionPredicatorEmitter - pass constant std::vector arguments by ArrayRef instead Silence pass by value warnings Fixes #89210 --- .../TableGen/MacroFusionPredicatorEmitter.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp b/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp index 63b827a35177..f61a05861981 100644 --- a/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp +++ b/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp @@ -55,11 +55,11 @@ class MacroFusionPredicatorEmitter { RecordKeeper &Records; CodeGenTarget Target; - void emitMacroFusionDecl(std::vector Fusions, PredicateExpander &PE, + void emitMacroFusionDecl(ArrayRef Fusions, PredicateExpander &PE, raw_ostream &OS); - void emitMacroFusionImpl(std::vector Fusions, PredicateExpander &PE, + void emitMacroFusionImpl(ArrayRef Fusions, PredicateExpander &PE, raw_ostream &OS); - void emitPredicates(std::vector &FirstPredicate, bool IsCommutable, + void emitPredicates(ArrayRef FirstPredicate, bool IsCommutable, PredicateExpander &PE, raw_ostream &OS); void emitFirstPredicate(Record *SecondPredicate, bool IsCommutable, PredicateExpander &PE, raw_ostream &OS); @@ -76,7 +76,7 @@ public: } // End anonymous namespace. void MacroFusionPredicatorEmitter::emitMacroFusionDecl( - std::vector Fusions, PredicateExpander &PE, raw_ostream &OS) { + ArrayRef Fusions, PredicateExpander &PE, raw_ostream &OS) { OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n"; OS << "#undef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n\n"; OS << "namespace llvm {\n"; @@ -93,7 +93,7 @@ void MacroFusionPredicatorEmitter::emitMacroFusionDecl( } void MacroFusionPredicatorEmitter::emitMacroFusionImpl( - std::vector Fusions, PredicateExpander &PE, raw_ostream &OS) { + ArrayRef Fusions, PredicateExpander &PE, raw_ostream &OS) { OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_IMPL\n"; OS << "#undef GET_" << Target.getName() << "_MACRO_FUSION_PRED_IMPL\n\n"; OS << "namespace llvm {\n"; @@ -121,9 +121,10 @@ void MacroFusionPredicatorEmitter::emitMacroFusionImpl( OS << "\n#endif\n"; } -void MacroFusionPredicatorEmitter::emitPredicates( - std::vector &Predicates, bool IsCommutable, PredicateExpander &PE, - raw_ostream &OS) { +void MacroFusionPredicatorEmitter::emitPredicates(ArrayRef Predicates, + bool IsCommutable, + PredicateExpander &PE, + raw_ostream &OS) { for (Record *Predicate : Predicates) { Record *Target = Predicate->getValueAsDef("Target"); if (Target->getName() == "first_fusion_target") -- GitLab From f02a27df2f133503b39bad38d0e2b3e95d3f8a23 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 19 Apr 2024 09:09:41 -0700 Subject: [PATCH 014/357] [ELF] Add --default-script/-dT GNU ld added --default-script (alias: -dT) in 2007. The option specifies a default script that is processed if --script/-T is not specified. -dT can be used to override GNU ld's internal linker script, but only when the application does not specify -T. In addition, dynamorio's CMakeLists.txt may use -dT. The implementation is simple and the feature can be useful to dabble with different section layouts. Pull Request: https://github.com/llvm/llvm-project/pull/89327 --- lld/ELF/Driver.cpp | 16 ++++-- lld/ELF/DriverUtils.cpp | 1 + lld/ELF/Options.td | 3 ++ lld/docs/ld.lld.1 | 4 ++ lld/test/ELF/linkerscript/default-script.s | 63 ++++++++++++++++++++++ lld/test/ELF/reproduce.s | 4 +- 6 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 lld/test/ELF/linkerscript/default-script.s diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 5fffdc51f34d..a5b47f020f87 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1856,8 +1856,9 @@ void LinkerDriver::createFiles(opt::InputArgList &args) { std::vector> stack; // Iterate over argv to process input files and positional arguments. + std::optional defaultScript; InputFile::isInGroup = false; - bool hasInput = false; + bool hasInput = false, hasScript = false; for (auto *arg : args) { switch (arg->getOption().getID()) { case OPT_library: @@ -1879,9 +1880,16 @@ void LinkerDriver::createFiles(opt::InputArgList &args) { break; } case OPT_script: + case OPT_default_script: if (std::optional path = searchScript(arg->getValue())) { - if (std::optional mb = readFile(*path)) - readLinkerScript(*mb); + if (std::optional mb = readFile(*path)) { + if (arg->getOption().matches(OPT_default_script)) { + defaultScript = mb; + } else { + readLinkerScript(*mb); + hasScript = true; + } + } break; } error(Twine("cannot find linker script ") + arg->getValue()); @@ -1961,6 +1969,8 @@ void LinkerDriver::createFiles(opt::InputArgList &args) { } } + if (defaultScript && !hasScript) + readLinkerScript(*defaultScript); if (files.empty() && !hasInput && errorCount() == 0) error("no input files"); } diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp index de8ffab0e212..ac7460440815 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -186,6 +186,7 @@ std::string elf::createResponseFile(const opt::InputArgList &args) { os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n"; break; case OPT_call_graph_ordering_file: + case OPT_default_script: case OPT_dynamic_list: case OPT_export_dynamic_symbol_list: case OPT_just_symbols: diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index d470646ed0ee..72eaf157a181 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -157,6 +157,8 @@ defm debug_names: BB<"debug-names", "Generate a merged .debug_names section", "Do not generate a merged .debug_names section (default)">; +defm default_script: EEq<"default-script", "In the absence of --script, read this default linker script">; + defm demangle: B<"demangle", "Demangle symbol names (default)", "Do not demangle symbol names">; @@ -555,6 +557,7 @@ HelpText<"Format diagnostics for Visual Studio compatibility">; def package_metadata: JJ<"package-metadata=">, HelpText<"Emit package metadata note">; // Aliases +def: Separate<["-"], "dT">, Alias, HelpText<"Alias for --default-script">; def: Separate<["-"], "f">, Alias, HelpText<"Alias for --auxiliary">; def: F<"call_shared">, Alias, HelpText<"Alias for --Bdynamic">; def: F<"dy">, Alias, HelpText<"Alias for --Bdynamic">; diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index ba8ce8f78475..3861120915e8 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -176,6 +176,10 @@ is specified, print to the map file. Generate a merged .Li .debug_names section. +.It Fl -default-script Ns = Ns Ar file , Fl dT Ar file +In the absence of +.Fl -script , +read this default linker script. .It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression Define a symbol alias. .Ar expression diff --git a/lld/test/ELF/linkerscript/default-script.s b/lld/test/ELF/linkerscript/default-script.s new file mode 100644 index 000000000000..bb716a5fe0cd --- /dev/null +++ b/lld/test/ELF/linkerscript/default-script.s @@ -0,0 +1,63 @@ +# REQUIRES: x86 +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o +# RUN: ld.lld --default-script=def.t b.t -T a.t a.o -o out +# RUN: llvm-readelf -Ss out | FileCheck %s + +# CHECK: Name +# CHECK: .foo2 +# CHECK-NEXT: .foo0 +# CHECK-NEXT: .foo1 +# CHECK: 1: 000000000000000c 0 NOTYPE GLOBAL DEFAULT 4 _start +# CHECK-NEXT: 2: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS b +# CHECK-NEXT: 3: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS a +# CHECK-EMPTY: + +## In the absence of --script options, the default linker script is read. +# RUN: ld.lld --default-script def.t b.t a.o -o out1 +# RUN: llvm-readelf -Ss out1 | FileCheck %s --check-prefix=CHECK1 +# RUN: ld.lld -dT def.t b.t a.o -o out1a && cmp out1 out1a +## If multiple -dT options are specified, the last -dT wins. +# RUN: ld.lld -dT a.t -dT def.t b.t a.o -o out1a && cmp out1 out1a + +# RUN: mkdir d && cp def.t d/default.t +# RUN: ld.lld -L d -dT default.t b.t a.o -o out1a && cmp out1 out1a + +# CHECK1: Name +# CHECK1: .foo2 +# CHECK1-NEXT: .foo1 +# CHECK1-NEXT: .foo0 +# CHECK1: 1: 000000000000000c 0 NOTYPE GLOBAL DEFAULT 4 _start +# CHECK1-NEXT: 2: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS b +# CHECK1-NEXT: 3: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS def +# CHECK1-EMPTY: + +# RUN: not ld.lld --default-script not-exist.t b.t -T a.t a.o 2>&1 | FileCheck %s --check-prefix=ERR +# ERR: error: cannot find linker script not-exist.t + +#--- a.s +.globl _start +_start: + +.section .foo0,"a"; .long 0 +.section .foo1,"a"; .long 0 +.section .foo2,"a"; .long 0 + +#--- a.t +a = 42; +SECTIONS { + .foo2 : {} + .foo0 : {} + .foo1 : {} +} + +#--- b.t +b = 42; + +#--- def.t +def = 42; +SECTIONS { + .foo2 : {} + .foo1 : {} + .foo0 : {} +} diff --git a/lld/test/ELF/reproduce.s b/lld/test/ELF/reproduce.s index 314c08b4f7cd..8818a9e35f40 100644 --- a/lld/test/ELF/reproduce.s +++ b/lld/test/ELF/reproduce.s @@ -34,10 +34,11 @@ # RUN: cp dyn dyn2 # RUN: echo > file # RUN: echo > file2 +# RUN: echo > file3 # RUN: echo "_start" > order # RUN: mkdir "sysroot with spaces" # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar' -# RUN: ld.lld --reproduce repro3.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 \ +# RUN: ld.lld --reproduce repro3.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 -dT file3 \ # RUN: --dynamic-list dyn --export-dynamic-symbol-list dyn2 -rpath file --script=file --symbol-ordering-file order \ # RUN: --sysroot "sysroot with spaces" --sysroot="sysroot with spaces" \ # RUN: --version-script ver --dynamic-linker "some unusual/path" -soname 'foo bar' \ @@ -48,6 +49,7 @@ # RSP3-NEXT: -L "[[BASEDIR:.+]]/foo bar" # RSP3-NEXT: -L [[BASEDIR]]/file # RSP3-NEXT: --script [[BASEDIR]]/file2 +# RSP3-NEXT: --default-script [[BASEDIR]]/file3 # RSP3-NEXT: --dynamic-list [[BASEDIR]]/dyn # RSP3-NEXT: --export-dynamic-symbol-list [[BASEDIR]]/dyn2 # RSP3-NEXT: -rpath [[BASEDIR]]/file -- GitLab From 854cc8986650267846c5eaf8ba164584a9ea7c01 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 19 Apr 2024 09:15:47 -0700 Subject: [PATCH 015/357] [libc] fixup nascent pthread_condattr_test (#89308) - use namespaced identifiers - add corresponding headers for namespaced declarations - replace time.h and errno.h with finer grain includes - update cmake Fixes: #88987 Fixes: #89261 Link: #88997 Link: #89262 --- libc/test/src/pthread/CMakeLists.txt | 4 +- .../src/pthread/pthread_condattr_test.cpp | 53 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt index 51954a5babd2..4d01b667f12c 100644 --- a/libc/test/src/pthread/CMakeLists.txt +++ b/libc/test/src/pthread/CMakeLists.txt @@ -47,9 +47,9 @@ add_libc_unittest( SRCS pthread_condattr_test.cpp DEPENDS - libc.include.errno + libc.include.llvm-libc-macros.generic_error_number_macros + libc.include.llvm-libc-macros.time_macros libc.include.pthread - libc.include.time libc.src.pthread.pthread_condattr_destroy libc.src.pthread.pthread_condattr_getclock libc.src.pthread.pthread_condattr_getpshared diff --git a/libc/test/src/pthread/pthread_condattr_test.cpp b/libc/test/src/pthread/pthread_condattr_test.cpp index accb62de92e4..5fcdbd99cb0e 100644 --- a/libc/test/src/pthread/pthread_condattr_test.cpp +++ b/libc/test/src/pthread/pthread_condattr_test.cpp @@ -6,16 +6,23 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL +#include "include/llvm-libc-macros/time-macros.h" // CLOCK_REALTIME, CLOCK_MONOTONIC +#include "src/pthread/pthread_condattr_destroy.h" +#include "src/pthread/pthread_condattr_getclock.h" +#include "src/pthread/pthread_condattr_getpshared.h" +#include "src/pthread/pthread_condattr_init.h" +#include "src/pthread/pthread_condattr_setclock.h" +#include "src/pthread/pthread_condattr_setpshared.h" #include "test/UnitTest/Test.h" -#include -#include -#include +// TODO: https://github.com/llvm/llvm-project/issues/88997 +#include // PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED TEST(LlvmLibcPThreadCondAttrTest, InitAndDestroy) { pthread_condattr_t cond; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } TEST(LlvmLibcPThreadCondAttrTest, GetDefaultValues) { @@ -26,12 +33,12 @@ TEST(LlvmLibcPThreadCondAttrTest, GetDefaultValues) { // Invalid value. int pshared = 42; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getclock(&cond, &clock), 0); ASSERT_EQ(clock, CLOCK_REALTIME); - ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getpshared(&cond, &pshared), 0); ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } TEST(LlvmLibcPThreadCondAttrTest, SetGoodValues) { @@ -42,14 +49,17 @@ TEST(LlvmLibcPThreadCondAttrTest, SetGoodValues) { // Invalid value. int pshared = 42; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_setclock(&cond, CLOCK_MONOTONIC), 0); - ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setclock(&cond, CLOCK_MONOTONIC), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getclock(&cond, &clock), 0); ASSERT_EQ(clock, CLOCK_MONOTONIC); - ASSERT_EQ(pthread_condattr_setpshared(&cond, PTHREAD_PROCESS_SHARED), 0); - ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setpshared(&cond, + PTHREAD_PROCESS_SHARED), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getpshared(&cond, &pshared), 0); ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } TEST(LlvmLibcPThreadCondAttrTest, SetBadValues) { @@ -60,12 +70,13 @@ TEST(LlvmLibcPThreadCondAttrTest, SetBadValues) { // Invalid value. int pshared = 42; - ASSERT_EQ(pthread_condattr_init(&cond), 0); - ASSERT_EQ(pthread_condattr_setclock(&cond, clock), EINVAL); - ASSERT_EQ(pthread_condattr_getclock(&cond, &clock), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_init(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setclock(&cond, clock), EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getclock(&cond, &clock), 0); ASSERT_EQ(clock, CLOCK_REALTIME); - ASSERT_EQ(pthread_condattr_setpshared(&cond, pshared), EINVAL); - ASSERT_EQ(pthread_condattr_getpshared(&cond, &pshared), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_setpshared(&cond, pshared), + EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_getpshared(&cond, &pshared), 0); ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); - ASSERT_EQ(pthread_condattr_destroy(&cond), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_condattr_destroy(&cond), 0); } -- GitLab From d86079f93c9f59d31f2cebb55dce24783070bd77 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 19 Apr 2024 09:21:57 -0700 Subject: [PATCH 016/357] [llvm-readelf] Print more information for RELR llvm-readelf/llvm-readobj print RELR as REL relocations with a fixed type (e.g. `R_*_RELATIVE`). GNU readelf printed only addresses and have recently switched to a more descritive style that includes a symbolic address column (symbolized using .symtab/.strtab) (milestone: binutils 2.43). This patch implements the new GNU style, which seems superior to the current REL style and essentially obsoletes LLVM-specific --raw-relr (`printRelrReloc`). Pull Request: https://github.com/llvm/llvm-project/pull/89162 --- lld/test/ELF/pack-dyn-relocs.s | 50 +++---- lld/test/ELF/partition-pack-dyn-relocs.s | 6 +- .../tools/llvm-readobj/ELF/relr-relocs.test | 141 +++++++++++++----- llvm/tools/llvm-readobj/ELFDumper.cpp | 130 +++++++++++++--- 4 files changed, 239 insertions(+), 88 deletions(-) diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s index dd5d366ae234..e267147759d4 100644 --- a/lld/test/ELF/pack-dyn-relocs.s +++ b/lld/test/ELF/pack-dyn-relocs.s @@ -328,31 +328,31 @@ // RELR64-NEXT: 0000000000030510 0000000200000101 R_AARCH64_ABS64 0000000000000000 zed2 + 0 // RELR64-EMPTY: // RELR64-NEXT: Relocation section '.relr.dyn' at offset {{.*}} contains 24 entries: -// RELR64-NEXT: Offset Info Type Symbol's Value Symbol's Name -// RELR64-NEXT: 0000000000030490 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030498 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304a0 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304a8 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304b0 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304b8 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304c0 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304c8 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304d8 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304e0 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304e8 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304f0 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 00000000000304f8 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030500 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030508 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030520 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030528 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030530 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030538 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030540 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030548 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030550 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030558 0000000000000403 R_AARCH64_RELATIVE -// RELR64-NEXT: 0000000000030560 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: Symbolic Address +// RELR64-NEXT: $d.0{{$}} +// RELR64-NEXT: $d.0 + 0x8 +// RELR64-NEXT: $d.0 + 0x10 +// RELR64-NEXT: $d.0 + 0x18 +// RELR64-NEXT: $d.0 + 0x20 +// RELR64-NEXT: $d.0 + 0x28 +// RELR64-NEXT: $d.0 + 0x30 +// RELR64-NEXT: $d.0 + 0x38 +// RELR64-NEXT: $d.0 + 0x48 +// RELR64-NEXT: $d.0 + 0x50 +// RELR64-NEXT: $d.0 + 0x58 +// RELR64-NEXT: $d.0 + 0x60 +// RELR64-NEXT: $d.0 + 0x68 +// RELR64-NEXT: $d.0 + 0x70 +// RELR64-NEXT: $d.0 + 0x78 +// RELR64-NEXT: $d.0 + 0x90 +// RELR64-NEXT: $d.0 + 0x98 +// RELR64-NEXT: $d.0 + 0xa0 +// RELR64-NEXT: $d.0 + 0xa8 +// RELR64-NEXT: $d.0 + 0xb0 +// RELR64-NEXT: $d.0 + 0xb8 +// RELR64-NEXT: $d.0 + 0xc0 +// RELR64-NEXT: $d.0 + 0xc8 +// RELR64-NEXT: $d.0 + 0xd0 // RELR64-EMPTY: // RELR64-NEXT: Hex dump of section '.data': // RELR64-NEXT: 0x00030490 90040300 00000000 91040300 00000000 . diff --git a/lld/test/ELF/partition-pack-dyn-relocs.s b/lld/test/ELF/partition-pack-dyn-relocs.s index 3727bcc21614..8127110e348c 100644 --- a/lld/test/ELF/partition-pack-dyn-relocs.s +++ b/lld/test/ELF/partition-pack-dyn-relocs.s @@ -29,9 +29,9 @@ // CHECK-EMPTY: // CHECK: Relocation section '.relr.dyn' -// CHECK-NEXT: Offset -// PART0-NEXT: 000000000000[[DATA_SEGMENT]]378 {{.*}} R_X86_64_RELATIVE -// PART1-NEXT: 000000000000[[DATA_SEGMENT]]340 {{.*}} R_X86_64_RELATIVE +// CHECK-NEXT: Address Symbolic Address +// PART0-NEXT: 000000000000[[DATA_SEGMENT]]378 p0{{$}} +// PART1-NEXT: 000000000000[[DATA_SEGMENT]]340 p1{{$}} // CHECK-EMPTY: .section .llvm_sympart,"",@llvm_sympart diff --git a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test index 91b148ebb6e3..9b59f991c051 100644 --- a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test +++ b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test @@ -47,29 +47,39 @@ # RAW-GNU1-NEXT: 00000000000f0501 # RAW-GNU1-NEXT: 000a700550400009 -# RUN: llvm-readelf --relocations %t1 | FileCheck --check-prefix=GNU1 %s -# GNU1: Relocation section '.relr.dyn' at offset 0x40 contains 21 entries: -# GNU1: 0000000000010d60 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000010d68 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000010da0 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020000 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020040 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020050 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020080 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020088 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020090 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020098 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020210 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 00000000000202a8 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 00000000000202d8 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 00000000000202e8 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 00000000000202f8 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020308 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020358 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020360 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020368 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020380 0000000000000008 R_X86_64_RELATIVE -# GNU1-NEXT: 0000000000020390 0000000000000008 R_X86_64_RELATIVE +# RUN: llvm-readelf --relocations %t1 | FileCheck --check-prefix=GNU1 --match-full-lines --strict-whitespace %s +# GNU1:Relocation section '.relr.dyn' at offset 0x40 contains 21 entries: +# GNU1-NEXT:Index: Entry Address Symbolic Address +# GNU1-NEXT:0000: 0000000000010d60 0000000000010d60 +# GNU1-NEXT:0001: 0000000000000103 0000000000010d68 +# GNU1-NEXT: 0000000000010da0 base + 0x30 +# GNU1-NEXT:0002: 0000000000020000 0000000000020000 foo +# GNU1-NEXT:0003: 00000000000f0501 0000000000020040 foo + 0x40 +# GNU1-NEXT: 0000000000020050 foo + 0x50 +# GNU1-NEXT: 0000000000020080 foo + 0x80 +# GNU1-NEXT: 0000000000020088 foo + 0x88 +# GNU1-NEXT: 0000000000020090 foo + 0x90 +# GNU1-NEXT: 0000000000020098 foo + 0x98 +# GNU1-NEXT:0004: 000a700550400009 0000000000020210 bar + 0x10 +# GNU1-NEXT: 00000000000202a8 bar + 0xa8 +# GNU1-NEXT: 00000000000202d8 bar + 0xd8 +# GNU1-NEXT: 00000000000202e8 bar + 0xe8 +# GNU1-NEXT: 00000000000202f8 bar + 0xf8 +# GNU1-NEXT: 0000000000020308 bar + 0x108 +# GNU1-NEXT: 0000000000020358 bar + 0x158 +# GNU1-NEXT: 0000000000020360 bar + 0x160 +# GNU1-NEXT: 0000000000020368 bar + 0x168 +# GNU1-NEXT: 0000000000020380 bar + 0x180 +# GNU1-NEXT: 0000000000020390 bar + 0x190 +# GNU1-NOT:{{.}} + +## The addresses are not symbolized in the absence of .symtab. +# RUN: llvm-objcopy --strip-all %t1 %t1.stripped +# RUN: llvm-readelf --relocations %t1.stripped | FileCheck --check-prefix=GNU1S --match-full-lines --strict-whitespace %s +# GNU1S:Relocation section '.relr.dyn' at offset 0x40 contains 21 entries: +# GNU1S-NEXT:Index: Entry Address Symbolic Address +# GNU1S-NEXT:0000: 0000000000010d60 0000000000010d60 +# GNU1S-NEXT:0001: 0000000000000103 0000000000010d68 --- !ELF FileHeader: @@ -83,6 +93,18 @@ Sections: Flags: [ SHF_ALLOC ] Entries: [ 0x0000000000010D60, 0x0000000000000103, 0x0000000000020000, 0x00000000000F0501, 0x000A700550400009 ] +Symbols: + - Name: bar + Value: 0x20200 + Section: .relr.dyn + - Name: foo + Value: 0x20000 + Section: .relr.dyn + - Name: base + Value: 0x10d70 + Section: .relr.dyn + - Name: ignored + Value: 0x20210 # RUN: yaml2obj --docnum=2 %s -o %t2 # RUN: llvm-readobj --relocations --raw-relr %t2 | \ @@ -124,22 +146,24 @@ Sections: # RAW-GNU2-NEXT: 000f0501 # RAW-GNU2-NEXT: 50400009 -# RUN: llvm-readelf --relocations %t2 | FileCheck --check-prefix=GNU2 %s -# GNU2: Relocation section '.relr.dyn' at offset 0x34 contains 14 entries: -# GNU2: 00010d60 00000008 R_386_RELATIVE -# GNU2-NEXT: 00010d64 00000008 R_386_RELATIVE -# GNU2-NEXT: 00010d80 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020000 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020020 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020028 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020040 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020044 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020048 00000008 R_386_RELATIVE -# GNU2-NEXT: 0002004c 00000008 R_386_RELATIVE -# GNU2-NEXT: 00020088 00000008 R_386_RELATIVE -# GNU2-NEXT: 000200d4 00000008 R_386_RELATIVE -# GNU2-NEXT: 000200ec 00000008 R_386_RELATIVE -# GNU2-NEXT: 000200f4 00000008 R_386_RELATIVE +# RUN: llvm-readelf --relocations %t2 | FileCheck --check-prefix=GNU2 --match-full-lines --strict-whitespace %s +# GNU2:Relocation section '.relr.dyn' at offset 0x34 contains 14 entries: +# GNU2-NEXT:Index: Entry Address Symbolic Address +# GNU2-NEXT:0000: 00010d60 00010d60 .relr.dyn +# GNU2-NEXT:0001: 00000103 00010d64 .relr.dyn + 0x4 +# GNU2-NEXT: 00010d80 .relr.dyn + 0x20 +# GNU2-NEXT:0002: 00020000 00020000 .relr.dyn + 0xf2a0 +# GNU2-NEXT:0003: 000f0501 00020020 .relr.dyn + 0xf2c0 +# GNU2-NEXT: 00020028 .relr.dyn + 0xf2c8 +# GNU2-NEXT: 00020040 .relr.dyn + 0xf2e0 +# GNU2-NEXT: 00020044 .relr.dyn + 0xf2e4 +# GNU2-NEXT: 00020048 .relr.dyn + 0xf2e8 +# GNU2-NEXT: 0002004c .relr.dyn + 0xf2ec +# GNU2-NEXT:0004: 50400009 00020088 .relr.dyn + 0xf328 +# GNU2-NEXT: 000200d4 .relr.dyn + 0xf374 +# GNU2-NEXT: 000200ec .relr.dyn + 0xf38c +# GNU2-NEXT: 000200f4 .relr.dyn + 0xf394 +# GNU2-NOT:{{.}} --- !ELF FileHeader: @@ -156,6 +180,11 @@ Sections: EntSize: [[ENTSIZE=]] ShType: [[SHTYPE=]] Link: [[LINK=]] +Symbols: + - Name: .relr.dyn + Type: STT_SECTION + Value: 0x10D60 + Section: .relr.dyn ## Check we report a warning when we are unable to dump relocations ## for a SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR section. @@ -175,7 +204,6 @@ Sections: # BROKEN-GNU: warning: '[[FILE]]': unable to get the number of relocations in [[SECNAME]] section with index 1: section [index 1] has invalid sh_entsize: expected 4, but got 1 # BROKEN-GNU: Relocation section '.relr.dyn' at offset 0x34 contains entries: -# BROKEN-GNU-NEXT: Offset Info Type Sym. Value Symbol's Name # BROKEN-GNU-NEXT: warning: '[[FILE]]': unable to read relocations from [[SECNAME]] section with index 1: section [index 1] has invalid sh_entsize: expected 4, but got 1 ## Case B: check the case when relocations can't be read from an SHT_ANDROID_RELR section. @@ -218,3 +246,36 @@ Sections: # RUN: FileCheck -DFILE=%t2.has.link --check-prefix=RAW-LLVM2 %s # RUN: llvm-readelf --relocations --raw-relr %t2.has.link 2>&1 | \ # RUN: FileCheck -DFILE=%t2.has.link --check-prefix=RAW-GNU2 %s + +## .symtab is invalid. Check we report a warning and print entries without symbolization. +# RUN: yaml2obj --docnum=3 -DENTSIZE=1 %s -o %t3.err1 +# RUN: llvm-readelf -r %t3.err1 2>&1 | FileCheck -DFILE=%t3.err1 --check-prefixes=GNU3,GNU3-ERR1 --match-full-lines %s +# RUN: yaml2obj --docnum=3 -DLINK=0xff %s -o %t3.err2 +# RUN: llvm-readelf -r %t3.err2 2>&1 | FileCheck -DFILE=%t3.err2 --check-prefixes=GNU3,GNU3-ERR2 --match-full-lines %s + +# GNU3:Index: Entry Address Symbolic Address +# GNU3-ERR1-NEXT:{{.*}}warning: '[[FILE]]': unable to read symbols from the SHT_SYMTAB section: section [index 2] has invalid sh_entsize: expected 24, but got 1 +# GNU3-ERR2-NEXT:{{.*}}warning: '[[FILE]]': unable to get the string table for the SHT_SYMTAB section: invalid section index: 255 +# GNU3-NEXT:0000: 0000000000010d60 0000000000010d60 +# GNU3-NEXT:0001: 0000000000000103 0000000000010d68 +# GNU3-NEXT: 0000000000010da0 +# GNU3-NOT:{{.}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Entries: [ 0x0000000000010D60, 0x0000000000000103 ] + - Name: .symtab + Type: SHT_SYMTAB + Link: [[LINK=.strtab]] + EntSize: [[ENTSIZE=0x18]] +Symbols: + - Name: bar + Value: 0x10D60 diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 1108672003fc..f145653ac743 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -411,6 +411,7 @@ protected: std::string getStaticSymbolName(uint32_t Index) const; StringRef getDynamicString(uint64_t Value) const; + std::pair> getSymtabAndStrtab() const; void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const; std::string getDynamicEntry(uint64_t Type, uint64_t Value) const; @@ -512,6 +513,28 @@ ELFDumper::getVersionTable(const Elf_Shdr &Sec, ArrayRef *SymTab, return *VersionsOrErr; } +template +std::pair::Elf_Sym_Range, std::optional> +ELFDumper::getSymtabAndStrtab() const { + assert(DotSymtabSec); + Elf_Sym_Range Syms(nullptr, nullptr); + std::optional StrTable; + if (Expected StrTableOrErr = + Obj.getStringTableForSymtab(*DotSymtabSec)) + StrTable = *StrTableOrErr; + else + reportUniqueWarning( + "unable to get the string table for the SHT_SYMTAB section: " + + toString(StrTableOrErr.takeError())); + + if (Expected SymsOrErr = Obj.symbols(DotSymtabSec)) + Syms = *SymsOrErr; + else + reportUniqueWarning("unable to read symbols from the SHT_SYMTAB section: " + + toString(SymsOrErr.takeError())); + return {Syms, StrTable}; +} + template void ELFDumper::printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const { @@ -525,20 +548,7 @@ void ELFDumper::printSymbolsHelper(bool IsDynamic, Syms = dynamic_symbols(); Entries = Syms.size(); } else if (DotSymtabSec) { - if (Expected StrTableOrErr = - Obj.getStringTableForSymtab(*DotSymtabSec)) - StrTable = *StrTableOrErr; - else - reportUniqueWarning( - "unable to get the string table for the SHT_SYMTAB section: " + - toString(StrTableOrErr.takeError())); - - if (Expected SymsOrErr = Obj.symbols(DotSymtabSec)) - Syms = *SymsOrErr; - else - reportUniqueWarning( - "unable to read symbols from the SHT_SYMTAB section: " + - toString(SymsOrErr.takeError())); + std::tie(Syms, StrTable) = getSymtabAndStrtab(); Entries = DotSymtabSec->getEntityCount(); } if (Syms.empty()) @@ -658,6 +668,7 @@ private: void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex, DataRegion ShndxTable, StringRef StrTable, uint32_t Bucket); + void printRelr(const Elf_Shdr &Sec); void printRelrReloc(const Elf_Relr &R) override; void printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) override; @@ -3882,6 +3893,12 @@ static bool isRelocationSec(const typename ELFT::Shdr &Sec, } template void GNUELFDumper::printRelocations() { + auto PrintAsRelr = [&](const Elf_Shdr &Sec) { + return !opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || + Sec.sh_type == ELF::SHT_ANDROID_RELR || + (this->Obj.getHeader().e_machine == EM_AARCH64 && + Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)); + }; auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected { // Android's packed relocation section needs to be unpacked first // to get the actual number of entries. @@ -3894,10 +3911,7 @@ template void GNUELFDumper::printRelocations() { return RelasOrErr->size(); } - if (!opts::RawRelr && - (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR || - (this->Obj.getHeader().e_machine == EM_AARCH64 && - Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR))) { + if (PrintAsRelr(Sec)) { Expected RelrsOrErr = this->Obj.relrs(Sec); if (!RelrsOrErr) return RelrsOrErr.takeError(); @@ -3926,13 +3940,89 @@ template void GNUELFDumper::printRelocations() { OS << "\nRelocation section '" << Name << "' at offset 0x" << utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum << " entries:\n"; - printRelocHeaderFields(OS, Sec.sh_type, this->Obj.getHeader()); - this->printRelocationsHelper(Sec); + + if (PrintAsRelr(Sec)) { + printRelr(Sec); + } else { + printRelocHeaderFields(OS, Sec.sh_type, this->Obj.getHeader()); + this->printRelocationsHelper(Sec); + } } if (!HasRelocSections) OS << "\nThere are no relocations in this file.\n"; } +template void GNUELFDumper::printRelr(const Elf_Shdr &Sec) { + Expected RangeOrErr = this->Obj.relrs(Sec); + if (!RangeOrErr) { + this->reportUniqueWarning("unable to read relocations from " + + this->describe(Sec) + ": " + + toString(RangeOrErr.takeError())); + return; + } + if (ELFT::Is64Bits) + OS << "Index: Entry Address Symbolic Address\n"; + else + OS << "Index: Entry Address Symbolic Address\n"; + + // If .symtab is available, collect its defined symbols and sort them by + // st_value. + SmallVector, 0> Syms; + if (this->DotSymtabSec) { + Elf_Sym_Range Symtab; + std::optional Strtab; + std::tie(Symtab, Strtab) = this->getSymtabAndStrtab(); + if (Symtab.size() && Strtab) { + for (auto [I, Sym] : enumerate(Symtab)) { + if (!Sym.st_shndx) + continue; + Syms.emplace_back(Sym.st_value, + this->getFullSymbolName(Sym, I, ArrayRef(), + *Strtab, false)); + } + } + } + llvm::stable_sort(Syms); + + typename ELFT::uint Base = 0; + size_t I = 0; + auto Print = [&](uint64_t Where) { + OS << format_hex_no_prefix(Where, ELFT::Is64Bits ? 16 : 8); + for (; I < Syms.size() && Syms[I].first <= Where; ++I) + ; + // Try symbolizing the address. Find the nearest symbol before or at the + // address and print the symbol and the address difference. + if (I) { + OS << " " << Syms[I - 1].second; + if (Syms[I - 1].first < Where) + OS << " + 0x" << Twine::utohexstr(Where - Syms[I - 1].first); + } + OS << '\n'; + }; + for (auto [Index, R] : enumerate(*RangeOrErr)) { + typename ELFT::uint Entry = R; + OS << formatv("{0:4}: ", Index) + << format_hex_no_prefix(Entry, ELFT::Is64Bits ? 16 : 8) << ' '; + if ((Entry & 1) == 0) { + Print(Entry); + Base = Entry + sizeof(typename ELFT::uint); + } else { + bool First = true; + for (auto Where = Base; Entry >>= 1; + Where += sizeof(typename ELFT::uint)) { + if (Entry & 1) { + if (First) + First = false; + else + OS.indent(ELFT::Is64Bits ? 24 : 16); + Print(Where); + } + } + Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(typename ELFT::uint); + } + } +} + // Print the offset of a particular section from anyone of the ranges: // [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER]. // If 'Type' does not fall within any of those ranges, then a string is -- GitLab From e553ac4d8148291914526f4f66f09e362ce0a63f Mon Sep 17 00:00:00 2001 From: Jeff Niu Date: Fri, 19 Apr 2024 09:23:00 -0700 Subject: [PATCH 017/357] [mlir][llvm] Port `overflowFlags` to a native operation property (RELAND) (#89410) This PR changes the LLVM dialect's IntegerOverflowFlags to be stored on operations as native properties. Reland to fix flang --- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 10 +-- .../ArithCommon/AttrToLLVMConverter.h | 22 +++--- .../mlir/Conversion/LLVMCommon/Pattern.h | 14 ++-- .../Conversion/LLVMCommon/VectorPattern.h | 16 ++-- .../mlir/Dialect/LLVMIR/LLVMInterfaces.td | 76 +++++++------------ mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 23 ++++-- .../include/mlir/Target/LLVMIR/ModuleImport.h | 3 +- .../ArithCommon/AttrToLLVMConverter.cpp | 7 -- mlir/lib/Conversion/LLVMCommon/Pattern.cpp | 19 +++-- .../Conversion/LLVMCommon/VectorPattern.cpp | 26 +++---- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 76 ++++++++++++++++++- mlir/lib/Target/LLVMIR/ModuleImport.cpp | 7 +- 12 files changed, 183 insertions(+), 116 deletions(-) diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index d909bda89cde..921eac2f8f4b 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2110,9 +2110,8 @@ struct XArrayCoorOpConversion const bool baseIsBoxed = coor.getMemref().getType().isa(); TypePair baseBoxTyPair = baseIsBoxed ? getBoxTypePair(coor.getMemref().getType()) : TypePair{}; - mlir::LLVM::IntegerOverflowFlagsAttr nsw = - mlir::LLVM::IntegerOverflowFlagsAttr::get( - rewriter.getContext(), mlir::LLVM::IntegerOverflowFlags::nsw); + mlir::LLVM::IntegerOverflowFlags nsw = + mlir::LLVM::IntegerOverflowFlags::nsw; // For each dimension of the array, generate the offset calculation. for (unsigned i = 0; i < rank; ++i, ++indexOffset, ++shapeOffset, @@ -2396,9 +2395,8 @@ private: auto cpnTy = fir::dyn_cast_ptrOrBoxEleTy(boxObjTy); mlir::Type llvmPtrTy = ::getLlvmPtrType(coor.getContext()); mlir::Type byteTy = ::getI8Type(coor.getContext()); - mlir::LLVM::IntegerOverflowFlagsAttr nsw = - mlir::LLVM::IntegerOverflowFlagsAttr::get( - rewriter.getContext(), mlir::LLVM::IntegerOverflowFlags::nsw); + mlir::LLVM::IntegerOverflowFlags nsw = + mlir::LLVM::IntegerOverflowFlags::nsw; for (unsigned i = 1, last = operands.size(); i < last; ++i) { if (auto arrTy = cpnTy.dyn_cast()) { diff --git a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h b/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h index 0891e2ba7be7..7ffc86133176 100644 --- a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h +++ b/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h @@ -31,11 +31,6 @@ convertArithFastMathAttrToLLVM(arith::FastMathFlagsAttr fmfAttr); LLVM::IntegerOverflowFlags convertArithOverflowFlagsToLLVM(arith::IntegerOverflowFlags arithFlags); -/// Creates an LLVM overflow attribute from a given arithmetic overflow -/// attribute. -LLVM::IntegerOverflowFlagsAttr -convertArithOverflowAttrToLLVM(arith::IntegerOverflowFlagsAttr flagsAttr); - /// Creates an LLVM rounding mode enum value from a given arithmetic rounding /// mode enum value. LLVM::RoundingMode @@ -72,6 +67,9 @@ public: } ArrayRef getAttrs() const { return convertedAttr.getAttrs(); } + LLVM::IntegerOverflowFlags getOverflowFlags() const { + return LLVM::IntegerOverflowFlags::none; + } private: NamedAttrList convertedAttr; @@ -89,19 +87,18 @@ public: // Get the name of the arith overflow attribute. StringRef arithAttrName = SourceOp::getIntegerOverflowAttrName(); // Remove the source overflow attribute. - auto arithAttr = dyn_cast_if_present( - convertedAttr.erase(arithAttrName)); - if (arithAttr) { - StringRef targetAttrName = TargetOp::getIntegerOverflowAttrName(); - convertedAttr.set(targetAttrName, - convertArithOverflowAttrToLLVM(arithAttr)); + if (auto arithAttr = dyn_cast_if_present( + convertedAttr.erase(arithAttrName))) { + overflowFlags = convertArithOverflowFlagsToLLVM(arithAttr.getValue()); } } ArrayRef getAttrs() const { return convertedAttr.getAttrs(); } + LLVM::IntegerOverflowFlags getOverflowFlags() const { return overflowFlags; } private: NamedAttrList convertedAttr; + LLVM::IntegerOverflowFlags overflowFlags = LLVM::IntegerOverflowFlags::none; }; template @@ -132,6 +129,9 @@ public: } ArrayRef getAttrs() const { return convertedAttr.getAttrs(); } + LLVM::IntegerOverflowFlags getOverflowFlags() const { + return LLVM::IntegerOverflowFlags::none; + } private: NamedAttrList convertedAttr; diff --git a/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h b/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h index f362167ee932..f3bf5b66398e 100644 --- a/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h +++ b/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h @@ -11,6 +11,7 @@ #include "mlir/Conversion/LLVMCommon/MemRefBuilder.h" #include "mlir/Conversion/LLVMCommon/TypeConverter.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Transforms/DialectConversion.h" namespace mlir { @@ -18,13 +19,16 @@ class CallOpInterface; namespace LLVM { namespace detail { +/// Handle generically setting flags as native properties on LLVM operations. +void setNativeProperties(Operation *op, IntegerOverflowFlags overflowFlags); + /// Replaces the given operation "op" with a new operation of type "targetOp" /// and given operands. -LogicalResult oneToOneRewrite(Operation *op, StringRef targetOp, - ValueRange operands, - ArrayRef targetAttrs, - const LLVMTypeConverter &typeConverter, - ConversionPatternRewriter &rewriter); +LogicalResult oneToOneRewrite( + Operation *op, StringRef targetOp, ValueRange operands, + ArrayRef targetAttrs, + const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter, + IntegerOverflowFlags overflowFlags = IntegerOverflowFlags::none); } // namespace detail } // namespace LLVM diff --git a/mlir/include/mlir/Conversion/LLVMCommon/VectorPattern.h b/mlir/include/mlir/Conversion/LLVMCommon/VectorPattern.h index 279175b6128f..964281592cc6 100644 --- a/mlir/include/mlir/Conversion/LLVMCommon/VectorPattern.h +++ b/mlir/include/mlir/Conversion/LLVMCommon/VectorPattern.h @@ -54,11 +54,11 @@ LogicalResult handleMultidimensionalVectors( std::function createOperand, ConversionPatternRewriter &rewriter); -LogicalResult vectorOneToOneRewrite(Operation *op, StringRef targetOp, - ValueRange operands, - ArrayRef targetAttrs, - const LLVMTypeConverter &typeConverter, - ConversionPatternRewriter &rewriter); +LogicalResult vectorOneToOneRewrite( + Operation *op, StringRef targetOp, ValueRange operands, + ArrayRef targetAttrs, + const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter, + IntegerOverflowFlags overflowFlags = IntegerOverflowFlags::none); } // namespace detail } // namespace LLVM @@ -70,6 +70,9 @@ public: AttrConvertPassThrough(SourceOp srcOp) : srcAttrs(srcOp->getAttrs()) {} ArrayRef getAttrs() const { return srcAttrs; } + LLVM::IntegerOverflowFlags getOverflowFlags() const { + return LLVM::IntegerOverflowFlags::none; + } private: ArrayRef srcAttrs; @@ -100,7 +103,8 @@ public: return LLVM::detail::vectorOneToOneRewrite( op, TargetOp::getOperationName(), adaptor.getOperands(), - attrConvert.getAttrs(), *this->getTypeConverter(), rewriter); + attrConvert.getAttrs(), *this->getTypeConverter(), rewriter, + attrConvert.getOverflowFlags()); } }; } // namespace mlir diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td index cee752aeb269..7085f81e203a 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td @@ -50,58 +50,40 @@ def FastmathFlagsInterface : OpInterface<"FastmathFlagsInterface"> { def IntegerOverflowFlagsInterface : OpInterface<"IntegerOverflowFlagsInterface"> { let description = [{ - Access to op integer overflow flags. + This interface defines an LLVM operation with integer overflow flags and + provides a uniform API for accessing them. }]; let cppNamespace = "::mlir::LLVM"; let methods = [ - InterfaceMethod< - /*desc=*/ "Returns an IntegerOverflowFlagsAttr attribute for the operation", - /*returnType=*/ "IntegerOverflowFlagsAttr", - /*methodName=*/ "getOverflowAttr", - /*args=*/ (ins), - /*methodBody=*/ [{}], - /*defaultImpl=*/ [{ - auto op = cast(this->getOperation()); - return op.getOverflowFlagsAttr(); - }] - >, - InterfaceMethod< - /*desc=*/ "Returns whether the operation has the No Unsigned Wrap keyword", - /*returnType=*/ "bool", - /*methodName=*/ "hasNoUnsignedWrap", - /*args=*/ (ins), - /*methodBody=*/ [{}], - /*defaultImpl=*/ [{ - auto op = cast(this->getOperation()); - IntegerOverflowFlags flags = op.getOverflowFlagsAttr().getValue(); - return bitEnumContainsAll(flags, IntegerOverflowFlags::nuw); - }] - >, - InterfaceMethod< - /*desc=*/ "Returns whether the operation has the No Signed Wrap keyword", - /*returnType=*/ "bool", - /*methodName=*/ "hasNoSignedWrap", - /*args=*/ (ins), - /*methodBody=*/ [{}], - /*defaultImpl=*/ [{ - auto op = cast(this->getOperation()); - IntegerOverflowFlags flags = op.getOverflowFlagsAttr().getValue(); - return bitEnumContainsAll(flags, IntegerOverflowFlags::nsw); - }] - >, - StaticInterfaceMethod< - /*desc=*/ [{Returns the name of the IntegerOverflowFlagsAttr attribute - for the operation}], - /*returnType=*/ "StringRef", - /*methodName=*/ "getIntegerOverflowAttrName", - /*args=*/ (ins), - /*methodBody=*/ [{}], - /*defaultImpl=*/ [{ - return "overflowFlags"; - }] - > + InterfaceMethod<[{ + Get the integer overflow flags for the operation. + }], "IntegerOverflowFlags", "getOverflowFlags", (ins), [{}], [{ + return $_op.getProperties().overflowFlags; + }]>, + InterfaceMethod<[{ + Set the integer overflow flags for the operation. + }], "void", "setOverflowFlags", (ins "IntegerOverflowFlags":$flags), [{}], [{ + $_op.getProperties().overflowFlags = flags; + }]>, + InterfaceMethod<[{ + Returns whether the operation has the No Unsigned Wrap keyword. + }], "bool", "hasNoUnsignedWrap", (ins), [{}], [{ + return bitEnumContainsAll($_op.getOverflowFlags(), + IntegerOverflowFlags::nuw); + }]>, + InterfaceMethod<[{ + Returns whether the operation has the No Signed Wrap keyword. + }], "bool", "hasNoSignedWrap", (ins), [{}], [{ + return bitEnumContainsAll($_op.getOverflowFlags(), + IntegerOverflowFlags::nsw); + }]>, + StaticInterfaceMethod<[{ + Get the attribute name of the overflow flags property. + }], "StringRef", "getOverflowFlagsAttrName", (ins), [{}], [{ + return "overflowFlags"; + }]>, ]; } diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index f8f9264b3889..eedae4b9bb7c 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -59,17 +59,30 @@ class LLVM_IntArithmeticOpWithOverflowFlag traits = []> : LLVM_ArithmeticOpBase], traits)> { - dag iofArg = ( - ins DefaultValuedAttr:$overflowFlags); + dag iofArg = (ins EnumProperty<"IntegerOverflowFlags">:$overflowFlags); let arguments = !con(commonArgs, iofArg); + + let builders = [ + OpBuilder<(ins "Type":$type, "Value":$lhs, "Value":$rhs, + "IntegerOverflowFlags":$overflowFlags), [{ + build($_builder, $_state, type, lhs, rhs); + $_state.getOrAddProperties().overflowFlags = overflowFlags; + }]>, + OpBuilder<(ins "Value":$lhs, "Value":$rhs, + "IntegerOverflowFlags":$overflowFlags), [{ + build($_builder, $_state, lhs, rhs); + $_state.getOrAddProperties().overflowFlags = overflowFlags; + }]> + ]; + string mlirBuilder = [{ auto op = $_builder.create<$_qualCppClassName>($_location, $lhs, $rhs); - moduleImport.setIntegerOverflowFlagsAttr(inst, op); + moduleImport.setIntegerOverflowFlags(inst, op); $res = op; }]; let assemblyFormat = [{ - $lhs `,` $rhs (`overflow` `` $overflowFlags^)? - custom(attr-dict) `:` type($res) + $lhs `,` $rhs `` custom($overflowFlags) + `` custom(attr-dict) `:` type($res) }]; string llvmBuilder = "$res = builder.Create" # instName # diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h index 1a188b1d0428..04d098d38155 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -183,8 +183,7 @@ public: /// Sets the integer overflow flags (nsw/nuw) attribute for the imported /// operation `op` given the original instruction `inst`. Asserts if the /// operation does not implement the integer overflow flag interface. - void setIntegerOverflowFlagsAttr(llvm::Instruction *inst, - Operation *op) const; + void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const; /// Sets the fastmath flags attribute for the imported operation `op` given /// the original instruction `inst`. Asserts if the operation does not diff --git a/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp b/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp index f12eba98480d..cf60a048f782 100644 --- a/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp +++ b/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp @@ -49,13 +49,6 @@ LLVM::IntegerOverflowFlags mlir::arith::convertArithOverflowFlagsToLLVM( return llvmFlags; } -LLVM::IntegerOverflowFlagsAttr mlir::arith::convertArithOverflowAttrToLLVM( - arith::IntegerOverflowFlagsAttr flagsAttr) { - arith::IntegerOverflowFlags arithFlags = flagsAttr.getValue(); - return LLVM::IntegerOverflowFlagsAttr::get( - flagsAttr.getContext(), convertArithOverflowFlagsToLLVM(arithFlags)); -} - LLVM::RoundingMode mlir::arith::convertArithRoundingModeToLLVM(arith::RoundingMode roundingMode) { switch (roundingMode) { diff --git a/mlir/lib/Conversion/LLVMCommon/Pattern.cpp b/mlir/lib/Conversion/LLVMCommon/Pattern.cpp index 83c31a204efc..1886dfa87096 100644 --- a/mlir/lib/Conversion/LLVMCommon/Pattern.cpp +++ b/mlir/lib/Conversion/LLVMCommon/Pattern.cpp @@ -329,14 +329,19 @@ LogicalResult ConvertToLLVMPattern::copyUnrankedDescriptors( // Detail methods //===----------------------------------------------------------------------===// +void LLVM::detail::setNativeProperties(Operation *op, + IntegerOverflowFlags overflowFlags) { + if (auto iface = dyn_cast(op)) + iface.setOverflowFlags(overflowFlags); +} + /// Replaces the given operation "op" with a new operation of type "targetOp" /// and given operands. -LogicalResult -LLVM::detail::oneToOneRewrite(Operation *op, StringRef targetOp, - ValueRange operands, - ArrayRef targetAttrs, - const LLVMTypeConverter &typeConverter, - ConversionPatternRewriter &rewriter) { +LogicalResult LLVM::detail::oneToOneRewrite( + Operation *op, StringRef targetOp, ValueRange operands, + ArrayRef targetAttrs, + const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter, + IntegerOverflowFlags overflowFlags) { unsigned numResults = op->getNumResults(); SmallVector resultTypes; @@ -352,6 +357,8 @@ LLVM::detail::oneToOneRewrite(Operation *op, StringRef targetOp, rewriter.create(op->getLoc(), rewriter.getStringAttr(targetOp), operands, resultTypes, targetAttrs); + setNativeProperties(newOp, overflowFlags); + // If the operation produced 0 or 1 result, return them immediately. if (numResults == 0) return rewriter.eraseOp(op), success(); diff --git a/mlir/lib/Conversion/LLVMCommon/VectorPattern.cpp b/mlir/lib/Conversion/LLVMCommon/VectorPattern.cpp index 544bcc71aca1..626135c10a3e 100644 --- a/mlir/lib/Conversion/LLVMCommon/VectorPattern.cpp +++ b/mlir/lib/Conversion/LLVMCommon/VectorPattern.cpp @@ -103,12 +103,11 @@ LogicalResult LLVM::detail::handleMultidimensionalVectors( return success(); } -LogicalResult -LLVM::detail::vectorOneToOneRewrite(Operation *op, StringRef targetOp, - ValueRange operands, - ArrayRef targetAttrs, - const LLVMTypeConverter &typeConverter, - ConversionPatternRewriter &rewriter) { +LogicalResult LLVM::detail::vectorOneToOneRewrite( + Operation *op, StringRef targetOp, ValueRange operands, + ArrayRef targetAttrs, + const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter, + IntegerOverflowFlags overflowFlags) { assert(!operands.empty()); // Cannot convert ops if their operands are not of LLVM type. @@ -118,14 +117,15 @@ LLVM::detail::vectorOneToOneRewrite(Operation *op, StringRef targetOp, auto llvmNDVectorTy = operands[0].getType(); if (!isa(llvmNDVectorTy)) return oneToOneRewrite(op, targetOp, operands, targetAttrs, typeConverter, - rewriter); + rewriter, overflowFlags); - auto callback = [op, targetOp, targetAttrs, &rewriter](Type llvm1DVectorTy, - ValueRange operands) { - return rewriter - .create(op->getLoc(), rewriter.getStringAttr(targetOp), operands, - llvm1DVectorTy, targetAttrs) - ->getResult(0); + auto callback = [op, targetOp, targetAttrs, overflowFlags, + &rewriter](Type llvm1DVectorTy, ValueRange operands) { + Operation *newOp = + rewriter.create(op->getLoc(), rewriter.getStringAttr(targetOp), + operands, llvm1DVectorTy, targetAttrs); + LLVM::detail::setNativeProperties(newOp, overflowFlags); + return newOp->getResult(0); }; return handleMultidimensionalVectors(op, operands, typeConverter, callback, diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 1db506e286b3..78ff24dae68b 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -47,6 +47,74 @@ using mlir::LLVM::linkage::getMaxEnumValForLinkage; #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc" +//===----------------------------------------------------------------------===// +// Property Helpers +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// IntegerOverflowFlags + +namespace mlir { +static Attribute convertToAttribute(MLIRContext *ctx, + IntegerOverflowFlags flags) { + return IntegerOverflowFlagsAttr::get(ctx, flags); +} + +static LogicalResult +convertFromAttribute(IntegerOverflowFlags &flags, Attribute attr, + function_ref emitError) { + auto flagsAttr = dyn_cast(attr); + if (!flagsAttr) { + return emitError() << "expected 'overflowFlags' attribute to be an " + "IntegerOverflowFlagsAttr, but got " + << attr; + } + flags = flagsAttr.getValue(); + return success(); +} +} // namespace mlir + +static ParseResult parseOverflowFlags(AsmParser &p, + IntegerOverflowFlags &flags) { + if (failed(p.parseOptionalKeyword("overflow"))) { + flags = IntegerOverflowFlags::none; + return success(); + } + if (p.parseLess()) + return failure(); + do { + StringRef kw; + SMLoc loc = p.getCurrentLocation(); + if (p.parseKeyword(&kw)) + return failure(); + std::optional flag = + symbolizeIntegerOverflowFlags(kw); + if (!flag) + return p.emitError(loc, + "invalid overflow flag: expected nsw, nuw, or none"); + flags = flags | *flag; + } while (succeeded(p.parseOptionalComma())); + return p.parseGreater(); +} + +static void printOverflowFlags(AsmPrinter &p, Operation *op, + IntegerOverflowFlags flags) { + if (flags == IntegerOverflowFlags::none) + return; + p << " overflow<"; + SmallVector strs; + if (bitEnumContainsAny(flags, IntegerOverflowFlags::nsw)) + strs.push_back("nsw"); + if (bitEnumContainsAny(flags, IntegerOverflowFlags::nuw)) + strs.push_back("nuw"); + llvm::interleaveComma(strs, p); + p << ">"; +} + +//===----------------------------------------------------------------------===// +// Attribute Helpers +//===----------------------------------------------------------------------===// + static constexpr const char kElemTypeAttrName[] = "elem_type"; static auto processFMFAttr(ArrayRef attrs) { @@ -70,12 +138,12 @@ static ParseResult parseLLVMOpAttrs(OpAsmParser &parser, static void printLLVMOpAttrs(OpAsmPrinter &printer, Operation *op, DictionaryAttr attrs) { auto filteredAttrs = processFMFAttr(attrs.getValue()); - if (auto iface = dyn_cast(op)) + if (auto iface = dyn_cast(op)) { printer.printOptionalAttrDict( - filteredAttrs, - /*elidedAttrs=*/{iface.getIntegerOverflowAttrName()}); - else + filteredAttrs, /*elidedAttrs=*/{iface.getOverflowFlagsAttrName()}); + } else { printer.printOptionalAttrDict(filteredAttrs); + } } /// Verifies `symbol`'s use in `op` to ensure the symbol is a valid and diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 9d41fa0da375..191b84acd56f 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -627,8 +627,8 @@ void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst, } } -void ModuleImport::setIntegerOverflowFlagsAttr(llvm::Instruction *inst, - Operation *op) const { +void ModuleImport::setIntegerOverflowFlags(llvm::Instruction *inst, + Operation *op) const { auto iface = cast(op); IntegerOverflowFlags value = {}; @@ -636,8 +636,7 @@ void ModuleImport::setIntegerOverflowFlagsAttr(llvm::Instruction *inst, value = bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap()); - auto attr = IntegerOverflowFlagsAttr::get(op->getContext(), value); - iface->setAttr(iface.getIntegerOverflowAttrName(), attr); + iface.setOverflowFlags(value); } void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst, -- GitLab From 1b79a34a56378f5b75fb0abd03bb7029ea1c60ec Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Fri, 19 Apr 2024 09:30:47 -0700 Subject: [PATCH 018/357] [clang] Add flag to experiment with cold function attributes (#89298) To be removed and promoted to a proper driver flag if experiments turn out fruitful. For now, this can be experimented with `-mllvm -pgo-cold-func-opt=[optsize|minsize|optnone|default] -mllvm -enable-pgo-force-function-attrs`. Original LLVM patch for this functionality: #69030 --- clang/lib/CodeGen/BackendUtil.cpp | 57 ++++++++++++------- .../test/CodeGen/pgo-force-function-attrs.ll | 12 ++++ 2 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 clang/test/CodeGen/pgo-force-function-attrs.ll diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 6cc00b85664f..22c3f8642ad8 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -104,6 +104,21 @@ static cl::opt ClSanitizeOnOptimizerEarlyEP( "sanitizer-early-opt-ep", cl::Optional, cl::desc("Insert sanitizers on OptimizerEarlyEP.")); +// Experiment to mark cold functions as optsize/minsize/optnone. +// TODO: remove once this is exposed as a proper driver flag. +static cl::opt ClPGOColdFuncAttr( + "pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden, + cl::desc( + "Function attribute to apply to cold functions as determined by PGO"), + cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default", + "Default (no attribute)"), + clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize", + "Mark cold functions with optsize."), + clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize", + "Mark cold functions with minsize."), + clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone", + "Mark cold functions with optnone."))); + extern cl::opt ProfileCorrelate; // Re-link builtin bitcodes after optimization @@ -768,42 +783,41 @@ void EmitAssemblyHelper::RunOptimizationPipeline( CodeGenOpts.InstrProfileOutput.empty() ? getDefaultProfileGenName() : CodeGenOpts.InstrProfileOutput, "", "", CodeGenOpts.MemoryProfileUsePath, nullptr, PGOOptions::IRInstr, - PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + PGOOptions::NoCSAction, ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, /*PseudoProbeForProfiling=*/false, CodeGenOpts.AtomicProfileUpdate); else if (CodeGenOpts.hasProfileIRUse()) { // -fprofile-use. auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse : PGOOptions::NoCSAction; - PGOOpt = PGOOptions( - CodeGenOpts.ProfileInstrumentUsePath, "", - CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS, - PGOOptions::IRUse, CSAction, PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling); + PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "", + CodeGenOpts.ProfileRemappingFile, + CodeGenOpts.MemoryProfileUsePath, VFS, + PGOOptions::IRUse, CSAction, ClPGOColdFuncAttr, + CodeGenOpts.DebugInfoForProfiling); } else if (!CodeGenOpts.SampleProfileFile.empty()) // -fprofile-sample-use PGOOpt = PGOOptions( CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::SampleUse, - PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, + PGOOptions::NoCSAction, ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling); else if (!CodeGenOpts.MemoryProfileUsePath.empty()) // -fmemory-profile-use (without any of the above options) PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::NoAction, PGOOptions::NoCSAction, - PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling); + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling); else if (CodeGenOpts.PseudoProbeForProfiling) // -fpseudo-probe-for-profiling - PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, - PGOOptions::NoAction, PGOOptions::NoCSAction, - PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling, true); + PGOOpt = + PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, + PGOOptions::NoAction, PGOOptions::NoCSAction, + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, true); else if (CodeGenOpts.DebugInfoForProfiling) // -fdebug-info-for-profiling PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, PGOOptions::NoCSAction, - PGOOptions::ColdFuncOpt::Default, true); + ClPGOColdFuncAttr, true); // Check to see if we want to generate a CS profile. if (CodeGenOpts.hasProfileCSIRInstr()) { @@ -820,14 +834,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline( : CodeGenOpts.InstrProfileOutput; PGOOpt->CSAction = PGOOptions::CSIRInstr; } else - PGOOpt = - PGOOptions("", - CodeGenOpts.InstrProfileOutput.empty() - ? getDefaultProfileGenName() - : CodeGenOpts.InstrProfileOutput, - "", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, - PGOOptions::CSIRInstr, PGOOptions::ColdFuncOpt::Default, - CodeGenOpts.DebugInfoForProfiling); + PGOOpt = PGOOptions("", + CodeGenOpts.InstrProfileOutput.empty() + ? getDefaultProfileGenName() + : CodeGenOpts.InstrProfileOutput, + "", /*MemoryProfile=*/"", nullptr, + PGOOptions::NoAction, PGOOptions::CSIRInstr, + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling); } if (TM) TM->setPGOOption(PGOOpt); diff --git a/clang/test/CodeGen/pgo-force-function-attrs.ll b/clang/test/CodeGen/pgo-force-function-attrs.ll new file mode 100644 index 000000000000..3e9ea95e4df4 --- /dev/null +++ b/clang/test/CodeGen/pgo-force-function-attrs.ll @@ -0,0 +1,12 @@ +; RUN: %clang_cc1 -O2 -mllvm -pgo-cold-func-opt=optsize -mllvm -enable-pgo-force-function-attrs -fprofile-sample-use=%S/Inputs/pgo-sample.prof %s -emit-llvm -o - | FileCheck %s --check-prefix=OPTSIZE +; Check that no profile means no optsize +; RUN: %clang_cc1 -O2 -mllvm -pgo-cold-func-opt=optsize -mllvm -enable-pgo-force-function-attrs %s -emit-llvm -o - | FileCheck %s --check-prefix=NONE +; Check that no -pgo-cold-func-opt=optsize means no optsize +; RUN: %clang_cc1 -O2 -mllvm -enable-pgo-force-function-attrs -fprofile-sample-use=%S/Inputs/pgo-sample.prof %s -emit-llvm -o - | FileCheck %s --check-prefix=NONE + +; NONE-NOT: optsize +; OPTSIZE: optsize + +define void @f() cold { + ret void +} -- GitLab From e6e931960b917e3a37f059a75d476966f572f787 Mon Sep 17 00:00:00 2001 From: Troy Butler <118708570+Troy-Butler@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:36:08 -0400 Subject: [PATCH 019/357] [LLVM][TextAPI] Refactor Redundant Condition (#86542) Fixes #83241 --------- Signed-off-by: Troy-Butler Co-authored-by: Troy-Butler --- llvm/lib/TextAPI/TextStub.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/TextAPI/TextStub.cpp b/llvm/lib/TextAPI/TextStub.cpp index 0f742523f820..d903ba409360 100644 --- a/llvm/lib/TextAPI/TextStub.cpp +++ b/llvm/lib/TextAPI/TextStub.cpp @@ -276,7 +276,7 @@ namespace yaml { template <> struct MappingTraits { static void mapping(IO &IO, ExportSection &Section) { const auto *Ctx = reinterpret_cast(IO.getContext()); - assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) && + assert((!Ctx || Ctx->FileKind != FileType::Invalid) && "File type is not set in YAML context"); IO.mapRequired("archs", Section.Architectures); @@ -298,7 +298,7 @@ template <> struct MappingTraits { template <> struct MappingTraits { static void mapping(IO &IO, UndefinedSection &Section) { const auto *Ctx = reinterpret_cast(IO.getContext()); - assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) && + assert((!Ctx || Ctx->FileKind != FileType::Invalid) && "File type is not set in YAML context"); IO.mapRequired("archs", Section.Architectures); -- GitLab From cd9f98de7309bf94369929b0bd957cd6f5e5a9ed Mon Sep 17 00:00:00 2001 From: Yijia Gu Date: Fri, 19 Apr 2024 09:38:51 -0700 Subject: [PATCH 020/357] [mlir][bazel] add bazel rule for XeGPU --- .../llvm-project-overlay/mlir/BUILD.bazel | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index ef4574f7c144..665e878a5781 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -3687,6 +3687,45 @@ cc_library( ], ) +gentbl_cc_library( + name = "XeGPUPassIncGen", + tbl_outs = [ + ( + [ + "-gen-pass-decls", + "-name=XeGPU", + ], + "include/mlir/Dialect/XeGPU/Transforms/Passes.h.inc", + ), + ], + tblgen = ":mlir-tblgen", + td_file = "include/mlir/Dialect/XeGPU/Transforms/Passes.td", + deps = [":PassBaseTdFiles"], +) + +cc_library( + name = "XeGPUTransforms", + srcs = glob([ + "lib/Dialect/XeGPU/Transforms/*.cpp", + ]), + hdrs = glob([ + "include/mlir/Dialect/XeGPU/Transforms/*.h", + ]), + includes = ["include"], + deps = [ + ":AffineUtils", + ":IR", + ":MemRefDialect", + ":Pass", + ":SideEffectInterfaces", + ":Support", + ":TransformUtils", + ":XeGPUDialect", + ":XeGPUPassIncGen", + “//llvm:Support", + ], +) + td_library( name = "FuncTdFiles", srcs = [ @@ -9229,6 +9268,7 @@ cc_library( ":X86VectorDialect", ":X86VectorTransforms", ":XeGPUDialect", + ":XeGPUTransforms", ":config", ], ) -- GitLab From e4f63202b926072e75997936806e659252a43077 Mon Sep 17 00:00:00 2001 From: Jorge Gorbe Moya Date: Fri, 19 Apr 2024 09:50:34 -0700 Subject: [PATCH 021/357] [bazel][mlir] Fix invalid quotation mark in BUILD file --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 665e878a5781..6c732b8f1349 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -3722,7 +3722,7 @@ cc_library( ":TransformUtils", ":XeGPUDialect", ":XeGPUPassIncGen", - “//llvm:Support", + "//llvm:Support", ], ) -- GitLab From 82c320ca59744b5082ef6e45dab6bab20cbd0795 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 19 Apr 2024 09:51:29 -0700 Subject: [PATCH 022/357] [ELF,test] Remove --raw-relr from pack-dyn-relocs.s --- lld/test/ELF/pack-dyn-relocs.s | 95 ++++++---------------------------- 1 file changed, 15 insertions(+), 80 deletions(-) diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s index e267147759d4..3cbba6871697 100644 --- a/lld/test/ELF/pack-dyn-relocs.s +++ b/lld/test/ELF/pack-dyn-relocs.s @@ -117,79 +117,22 @@ // ANDROID32-NEXT: } // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a32.o %t.a32.so -o %t4.a32 -// RUN: llvm-readobj -S --dynamic-table %t4.a32 | FileCheck --check-prefix=RELR32-HEADERS %s -// RUN: llvm-readobj -r --raw-relr %t4.a32 | FileCheck --check-prefix=RAW-RELR32 %s -// RUN: llvm-readobj -r %t4.a32 | FileCheck --check-prefix=RELR32 %s - -// RELR32-HEADERS: Index: 1 -// RELR32-HEADERS-NEXT: Name: .dynsym - -// RELR32-HEADERS: Name: .relr.dyn -// RELR32-HEADERS-NEXT: Type: SHT_RELR -// RELR32-HEADERS-NEXT: Flags [ (0x2) -// RELR32-HEADERS-NEXT: SHF_ALLOC (0x2) -// RELR32-HEADERS-NEXT: ] -// RELR32-HEADERS-NEXT: Address: [[ADDR:.*]] -// RELR32-HEADERS-NEXT: Offset: [[ADDR]] -// RELR32-HEADERS-NEXT: Size: 8 -// RELR32-HEADERS-NEXT: Link: 0 -// RELR32-HEADERS-NEXT: Info: 0 -// RELR32-HEADERS-NEXT: AddressAlignment: 4 -// RELR32-HEADERS-NEXT: EntrySize: 4 - -// RELR32-HEADERS: 0x00000024 RELR [[ADDR]] -// RELR32-HEADERS: 0x00000023 RELRSZ 8 (bytes) -// RELR32-HEADERS: 0x00000025 RELRENT 4 (bytes) - -/// SHT_RELR section contains address/bitmap entries -/// encoding the offsets for relative relocation. -// RAW-RELR32: Section ({{.+}}) .relr.dyn { -// RAW-RELR32-NEXT: 0x30284 -// RAW-RELR32-NEXT: 0x7FCFEFF -// RAW-RELR32-NEXT: } +// RUN: llvm-readelf -Sdr %t4.a32 | FileCheck --check-prefix=RELR32 %s -/// Decoded SHT_RELR section is same as UNPACKED, -/// but contains only the relative relocations. -/// Any relative relocations with odd offset stay in SHT_REL. -// RELR32: Section ({{.+}}) .rel.dyn { -// RELR32-NEXT: 0x302F1 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302A4 R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x302C8 R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x302F5 R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x302F9 R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x302FD R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x30301 R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x30305 R_ARM_ABS32 bar2 -// RELR32-NEXT: 0x302C4 R_ARM_ABS32 zed2 -// RELR32-NEXT: } -// RELR32-NEXT: Section ({{.+}}) .relr.dyn { -// RELR32-NEXT: 0x30284 R_ARM_RELATIVE - -// RELR32-NEXT: 0x30288 R_ARM_RELATIVE - -// RELR32-NEXT: 0x3028C R_ARM_RELATIVE - -// RELR32-NEXT: 0x30290 R_ARM_RELATIVE - -// RELR32-NEXT: 0x30294 R_ARM_RELATIVE - -// RELR32-NEXT: 0x30298 R_ARM_RELATIVE - -// RELR32-NEXT: 0x3029C R_ARM_RELATIVE - -// RELR32-NEXT: 0x302A0 R_ARM_RELATIVE - - -// RELR32-NEXT: 0x302A8 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302AC R_ARM_RELATIVE - -// RELR32-NEXT: 0x302B0 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302B4 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302B8 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302BC R_ARM_RELATIVE - -// RELR32-NEXT: 0x302C0 R_ARM_RELATIVE - - -// RELR32-NEXT: 0x302CC R_ARM_RELATIVE - -// RELR32-NEXT: 0x302D0 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302D4 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302D8 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302DC R_ARM_RELATIVE - -// RELR32-NEXT: 0x302E0 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302E4 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302E8 R_ARM_RELATIVE - -// RELR32-NEXT: 0x302EC R_ARM_RELATIVE - -// RELR32-NEXT: } +// RELR32: Name Type Address Off Size ES Flg Lk Inf Al +// RELR32: .dynstr STRTAB {{.*}} 00 A 0 0 1 +// RELR32-NEXT: .rel.dyn REL {{.*}} 08 A 1 0 4 +// RELR32-NEXT: .relr.dyn RELR {{0*}}[[#%x,RELR:]] {{.*}} 04 A 0 0 4 + +// RELR32: (RELCOUNT) 1 +// RELR32: (RELR) 0x[[#RELR]] +// RELR32-NEXT: (RELRSZ) 8 (bytes) +// RELR32-NEXT: (RELRENT) 4 (bytes) + +// RELR32: Relocation section '.relr.dyn' at offset {{.*}} contains 24 entries: +// RELR32-NEXT: Index: Entry Address Symbolic Address +// RELR32-NEXT: 0000: 00030284 {{.*}} +// RELR32-NEXT: 0001: 07fcfeff {{.*}} // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/shared2.s -o %t.a64.so.o // RUN: ld.lld -shared %t.a64.so.o -soname=so -o %t.a64.so @@ -292,7 +235,6 @@ // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64.o %t.a64.so -o %t4.a64 // RUN: llvm-readelf -Sdr -x .data %t4.a64 | FileCheck --check-prefix=RELR64 %s -// RUN: llvm-readobj -r --raw-relr %t4.a64 | FileCheck --check-prefix=RAW-RELR64 %s // RELR64: Name Type Address Off Size ES Flg Lk Inf Al // RELR64: .dynstr STRTAB {{.*}} 00 A 0 0 1 @@ -305,13 +247,6 @@ // RELR64-NEXT: (RELRSZ) 16 (bytes) // RELR64-NEXT: (RELRENT) 8 (bytes) -/// SHT_RELR section contains address/bitmap entries -/// encoding the offsets for relative relocation. -// RAW-RELR64: Section ({{.+}}) .relr.dyn { -// RAW-RELR64-NEXT: 0x30490 -// RAW-RELR64-NEXT: 0x7FCFEFF -// RAW-RELR64-NEXT: } - /// Decoded SHT_RELR section is same as UNPACKED, /// but contains only the relative relocations. /// Any relative relocations with odd offset stay in SHT_RELA. -- GitLab From 41e696291c64fe19629e14887ed1ed9b9c2271f0 Mon Sep 17 00:00:00 2001 From: LRFLEW Date: Fri, 19 Apr 2024 11:58:18 -0500 Subject: [PATCH 023/357] linear_congruential_engine: add using more precision to prevent overflow (#81583) This PR is a followup to #81080. This PR makes two major changes to how the LCG operation is computed: The first is that I added an additional case where `ax + c` might overflow the intermediate variable, but `ax` by itself won't. In this case, it's much better to use `(ax mod m) + c mod m` than the previous behavior of falling back to Schrage's algorithm. The addition modulo is done in the same way as when using Schrage's algorithm (i.e. `x += c - (x >= m - c)*m`), but the multiplication modulo is calculated directly, which is faster. The second is that I added handling for the case where the `ax` intermediate might overflow, but Schrage's algorithm doesn't apply (i.e. r > q). In this case, the only real option is to increase the precision of the intermediate values. The good news is that - for `x`, `a`, and `c` being n-bit values - `ax + c` will never overflow a 2n-bit intermediary, meaning this promotion can only happen once, and will always be able to use the simplest implementation. This is already the case for 16-bit LCGs, as libcxx chooses to compute them with 32-bit intermediate values. For 32-bit LCGs, I simply added code similar to the 16-bit case to use the existing 64-bit implementations. Lastly, for 64-bit LCGs, I wrote a case that calculates it using `unsigned __int128` if it is available to use. While this implementation covers a *lot* of the missing cases from #81080, this still won't compile **every** possible `linear_congruential_engine`. Specifically, if `a`, `c`, and `m` are chosen such that it needs 128-bit integers, but the platform doesn't support `__int128` (eg. 32-bit x86), then it will fail to compile. However, this is a fairly rare case to see actually used, and libcxx would be in good company with this, as [libstdc++ also fails to compile under these circumstances](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87744). Fixing **this** gap would require even **more** work of further complexity, so that would probably be best handled by a different PR (I'll put more details on what that PR would entail in a comment). --- .../__random/linear_congruential_engine.h | 103 ++++++++++++++---- .../rand/rand.eng/rand.eng.lcong/alg.pass.cpp | 65 ++++++++--- .../rand.eng/rand.eng.lcong/assign.pass.cpp | 18 ++- .../rand.eng/rand.eng.lcong/copy.pass.cpp | 18 ++- .../rand.eng/rand.eng.lcong/default.pass.cpp | 18 ++- .../rand.eng/rand.eng.lcong/values.pass.cpp | 18 ++- 6 files changed, 187 insertions(+), 53 deletions(-) diff --git a/libcxx/include/__random/linear_congruential_engine.h b/libcxx/include/__random/linear_congruential_engine.h index fe9cb909b74d..9d77649e9cfc 100644 --- a/libcxx/include/__random/linear_congruential_engine.h +++ b/libcxx/include/__random/linear_congruential_engine.h @@ -26,32 +26,60 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +enum __lce_alg_type { + _LCE_Full, + _LCE_Part, + _LCE_Schrage, + _LCE_Promote, +}; + template (_Mp - __c) / __a), - bool _OverflowOK = ((__m & (__m - 1)) == 0ull), // m = 2^n - bool _SchrageOK = (__a != 0 && __m != 0 && __m % __a <= __m / __a)> // r <= q + bool _HasOverflow = (__a != 0ull && (__m & (__m - 1ull)) != 0ull), // a != 0, m != 0, m != 2^n + bool _Full = (!_HasOverflow || __m - 1ull <= (_Mp - __c) / __a), // (a * x + c) % m works + bool _Part = (!_HasOverflow || __m - 1ull <= _Mp / __a), // (a * x) % m works + bool _Schrage = (_HasOverflow && __m % __a <= __m / __a)> // r <= q struct __lce_alg_picker { - static_assert(!_MightOverflow || _OverflowOK || _SchrageOK, - "The current values of a, c, and m cannot generate a number " - "within bounds of linear_congruential_engine."); - - static _LIBCPP_CONSTEXPR const bool __use_schrage = _MightOverflow && !_OverflowOK && _SchrageOK; + static _LIBCPP_CONSTEXPR const __lce_alg_type __mode = + _Full ? _LCE_Full + : _Part ? _LCE_Part + : _Schrage ? _LCE_Schrage + : _LCE_Promote; + +#ifdef _LIBCPP_HAS_NO_INT128 + static_assert(_Mp != (unsigned long long)(-1) || _Full || _Part || _Schrage, + "The current values for a, c, and m are not currently supported on platforms without __int128"); +#endif }; template ::__use_schrage> + __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode> struct __lce_ta; // 64 +#ifndef _LIBCPP_HAS_NO_INT128 +template +struct __lce_ta<_Ap, _Cp, _Mp, (unsigned long long)(-1), _LCE_Promote> { + typedef unsigned long long result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __xp) { + __extension__ using __calc_type = unsigned __int128; + const __calc_type __a = static_cast<__calc_type>(_Ap); + const __calc_type __c = static_cast<__calc_type>(_Cp); + const __calc_type __m = static_cast<__calc_type>(_Mp); + const __calc_type __x = static_cast<__calc_type>(__xp); + return static_cast((__a * __x + __c) % __m); + } +}; +#endif + template -struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), true> { +struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Schrage> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { // Schrage's algorithm @@ -66,7 +94,7 @@ struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), true> { }; template -struct __lce_ta<__a, 0, __m, (unsigned long long)(~0), true> { +struct __lce_ta<__a, 0ull, __m, (unsigned long long)(-1), _LCE_Schrage> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { // Schrage's algorithm @@ -80,21 +108,40 @@ struct __lce_ta<__a, 0, __m, (unsigned long long)(~0), true> { }; template -struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), false> { +struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Part> { + typedef unsigned long long result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { + // Use (((a*x) % m) + c) % m + __x = (__a * __x) % __m; + __x += __c - (__x >= __m - __c) * __m; + return __x; + } +}; + +template +struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Full> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return (__a * __x + __c) % __m; } }; template -struct __lce_ta<__a, __c, 0, (unsigned long long)(~0), false> { +struct __lce_ta<__a, __c, 0ull, (unsigned long long)(-1), _LCE_Full> { typedef unsigned long long result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return __a * __x + __c; } }; // 32 +template +struct __lce_ta<__a, __c, __m, unsigned(-1), _LCE_Promote> { + typedef unsigned result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { + return static_cast(__lce_ta<__a, __c, __m, (unsigned long long)(-1)>::next(__x)); + } +}; + template -struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), true> { +struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Schrage> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -112,7 +159,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), true> { }; template -struct __lce_ta<_Ap, 0, _Mp, unsigned(~0), true> { +struct __lce_ta<_Ap, 0ull, _Mp, unsigned(-1), _LCE_Schrage> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -128,7 +175,21 @@ struct __lce_ta<_Ap, 0, _Mp, unsigned(~0), true> { }; template -struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), false> { +struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Part> { + typedef unsigned result_type; + _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { + const result_type __a = static_cast(_Ap); + const result_type __c = static_cast(_Cp); + const result_type __m = static_cast(_Mp); + // Use (((a*x) % m) + c) % m + __x = (__a * __x) % __m; + __x += __c - (__x >= __m - __c) * __m; + return __x; + } +}; + +template +struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Full> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -139,7 +200,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), false> { }; template -struct __lce_ta<_Ap, _Cp, 0, unsigned(~0), false> { +struct __lce_ta<_Ap, _Cp, 0ull, unsigned(-1), _LCE_Full> { typedef unsigned result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { const result_type __a = static_cast(_Ap); @@ -150,11 +211,11 @@ struct __lce_ta<_Ap, _Cp, 0, unsigned(~0), false> { // 16 -template -struct __lce_ta<__a, __c, __m, (unsigned short)(~0), __b> { +template +struct __lce_ta<__a, __c, __m, (unsigned short)(-1), __mode> { typedef unsigned short result_type; _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { - return static_cast(__lce_ta<__a, __c, __m, unsigned(~0)>::next(__x)); + return static_cast(__lce_ta<__a, __c, __m, unsigned(-1)>::next(__x)); } }; @@ -178,7 +239,7 @@ public: private: result_type __x_; - static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(~0); + static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(-1); static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters"); static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters"); diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/alg.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/alg.pass.cpp index 8a9cae0e610c..159cb19f6546 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/alg.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/alg.pass.cpp @@ -38,12 +38,12 @@ int main(int, char**) // m might overflow. The overflow is not OK and result will be in bounds // so we should use Schrage's algorithm - typedef std::linear_congruential_engine E2; + typedef std::linear_congruential_engine E2; E2 e2; // make sure Schrage's algorithm is used (it would be 0s after the first otherwise) assert(e2() == (1ull << 32)); assert(e2() == (1ull << 63) - 1ull); - assert(e2() == (1ull << 63) - (1ull << 33) + 1ull); + assert(e2() == (1ull << 63) - 0x1ffffffffull); // make sure result is in bounds assert(e2() < (1ull << 63) + 1); assert(e2() < (1ull << 63) + 1); @@ -56,9 +56,9 @@ int main(int, char**) typedef std::linear_congruential_engine E3; E3 e3; // make sure Schrage's algorithm is used - assert(e3() == 402727752ull); - assert(e3() == 162159612030764687ull); - assert(e3() == 108176466184989142ull); + assert(e3() == 0x18012348ull); + assert(e3() == 0x2401b4ed802468full); + assert(e3() == 0x18051ec400369d6ull); // make sure result is in bounds assert(e3() < (3ull << 56)); assert(e3() < (3ull << 56)); @@ -66,19 +66,52 @@ int main(int, char**) assert(e3() < (3ull << 56)); assert(e3() < (3ull << 56)); - // m will not overflow so we should not use Schrage's algorithm - typedef std::linear_congruential_engine E4; + // 32-bit case: + // m might overflow. The overflow is not OK, result will be in bounds, + // and Schrage's algorithm is incompatible here. Need to use 64 bit arithmetic. + typedef std::linear_congruential_engine E4; E4 e4; + // make sure enough precision is used + assert(e4() == 0x10009u); + assert(e4() == 0x120053u); + assert(e4() == 0xf5030fu); + // make sure result is in bounds + assert(e4() < 0x7fffffffu); + assert(e4() < 0x7fffffffu); + assert(e4() < 0x7fffffffu); + assert(e4() < 0x7fffffffu); + assert(e4() < 0x7fffffffu); + +#ifndef _LIBCPP_HAS_NO_INT128 + // m might overflow. The overflow is not OK, result will be in bounds, + // and Schrage's algorithm is incompatible here. Need to use 128 bit arithmetic. + typedef std::linear_congruential_engine E5; + E5 e5; + // make sure enough precision is used + assert(e5() == 0x100000001ull); + assert(e5() == 0x200000009ull); + assert(e5() == 0xb00000019ull); + // make sure result is in bounds + assert(e5() < (1ull << 61) - 1ull); + assert(e5() < (1ull << 61) - 1ull); + assert(e5() < (1ull << 61) - 1ull); + assert(e5() < (1ull << 61) - 1ull); + assert(e5() < (1ull << 61) - 1ull); +#endif + + // m will not overflow so we should not use Schrage's algorithm + typedef std::linear_congruential_engine E6; + E6 e6; // make sure the correct algorithm was used - assert(e4() == 2ull); - assert(e4() == 3ull); - assert(e4() == 4ull); + assert(e6() == 2ull); + assert(e6() == 3ull); + assert(e6() == 4ull); // make sure result is in bounds - assert(e4() < (1ull << 48)); - assert(e4() < (1ull << 48)); - assert(e4() < (1ull << 48)); - assert(e4() < (1ull << 48)); - assert(e4() < (1ull << 48)); + assert(e6() < (1ull << 48)); + assert(e6() < (1ull << 48)); + assert(e6() < (1ull << 48)); + assert(e6() < (1ull << 48)); + assert(e6() < (1ull << 48)); return 0; -} \ No newline at end of file +} diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp index 5317f171a98a..73829071bd95 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp @@ -61,24 +61,34 @@ test() test1(); test1(); test1(); +} + +template +void test_ext() { + const T M(static_cast(-1)); - /* - // Cases where m is odd and m % a > m / a (not implemented) + // Cases where m is odd and m % a > m / a test1(); test1(); test1(); test1(); test1(); test1(); - */ } int main(int, char**) { test(); + test_ext(); test(); + test_ext(); test(); + test_ext(); test(); + // This isn't implemented on platforms without __int128 +#ifndef _LIBCPP_HAS_NO_INT128 + test_ext(); +#endif - return 0; + return 0; } diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp index 8e950043d594..8387a1763714 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp @@ -60,24 +60,34 @@ test() test1(); test1(); test1(); +} + +template +void test_ext() { + const T M(static_cast(-1)); - /* - // Cases where m is odd and m % a > m / a (not implemented) + // Cases where m is odd and m % a > m / a test1(); test1(); test1(); test1(); test1(); test1(); - */ } int main(int, char**) { test(); + test_ext(); test(); + test_ext(); test(); + test_ext(); test(); + // This isn't implemented on platforms without __int128 +#ifndef _LIBCPP_HAS_NO_INT128 + test_ext(); +#endif - return 0; + return 0; } diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/default.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/default.pass.cpp index 52126f7a200d..c59afd7a3eb2 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/default.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/default.pass.cpp @@ -58,24 +58,34 @@ test() test1(); test1(); test1(); +} + +template +void test_ext() { + const T M(static_cast(-1)); - /* - // Cases where m is odd and m % a > m / a (not implemented) + // Cases where m is odd and m % a > m / a test1(); test1(); test1(); test1(); test1(); test1(); - */ } int main(int, char**) { test(); + test_ext(); test(); + test_ext(); test(); + test_ext(); test(); + // This isn't implemented on platforms without __int128 +#ifndef _LIBCPP_HAS_NO_INT128 + test_ext(); +#endif - return 0; + return 0; } diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/values.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/values.pass.cpp index 28d8dfea01fa..98b07e70f247 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/values.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/values.pass.cpp @@ -91,24 +91,34 @@ test() test1(); test1(); test1(); +} - /* - // Cases where m is odd and m % a > m / a (not implemented) +template +void test_ext() { + const T M(static_cast(-1)); + + // Cases where m is odd and m % a > m / a test1(); test1(); test1(); test1(); test1(); test1(); - */ } int main(int, char**) { test(); + test_ext(); test(); + test_ext(); test(); + test_ext(); test(); + // This isn't implemented on platforms without __int128 +#ifndef _LIBCPP_HAS_NO_INT128 + test_ext(); +#endif - return 0; + return 0; } -- GitLab From 6bbccd2516c3a843809a8303da48abce58a88855 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 19 Apr 2024 10:01:42 -0700 Subject: [PATCH 024/357] GlobalsModRef, ValueTracking: Look through threadlocal.address intrinsic (#88418) This improves handling of `threadlocal.address` intrinsic in analyses: The thread-id cannot change within a function with the exception of suspend points of pre-split coroutines. This changes `llvm::getUnderlyingObject` to look through `threadlocal.address` in these cases. `GlobalsAAResult::AnalyzeUsesOfPointer` checks whether an address can be traced to simple loads/stores or escapes to other places. Starting the analysis from a thread-local `GlobalValue` the `threadlocal.address` intrinsic is safe to skip here. This improves issue #87437 --- llvm/include/llvm/Analysis/ValueTracking.h | 10 +-- llvm/lib/Analysis/GlobalsModRef.cpp | 8 +++ llvm/lib/Analysis/ValueTracking.cpp | 4 ++ .../GlobalsModRef/nonescaping-noalias.ll | 61 +++++++++++++++++++ ...aix-small-local-dynamic-tls-largeaccess.ll | 60 +++++++++--------- .../aix-small-local-exec-tls-largeaccess.ll | 44 ++++++------- .../aix-small-tls-globalvarattr-funcattr.ll | 6 +- llvm/test/CodeGen/X86/threadlocal_address.ll | 4 +- 8 files changed, 135 insertions(+), 62 deletions(-) diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index e1c41b3b55cc..bab7c8868532 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -690,11 +690,11 @@ inline Value *getArgumentAliasingToReturnedPointer(CallBase *Call, bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( const CallBase *Call, bool MustPreserveNullness); -/// This method strips off any GEP address adjustments and pointer casts from -/// the specified value, returning the original object being addressed. Note -/// that the returned value has pointer type if the specified value does. If -/// the MaxLookup value is non-zero, it limits the number of instructions to -/// be stripped off. +/// This method strips off any GEP address adjustments, pointer casts +/// or `llvm.threadlocal.address` from the specified value \p V, returning the +/// original object being addressed. Note that the returned value has pointer +/// type if the specified value does. If the \p MaxLookup value is non-zero, it +/// limits the number of instructions to be stripped off. const Value *getUnderlyingObject(const Value *V, unsigned MaxLookup = 6); inline Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6) { // Force const to avoid infinite recursion. diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp index 527f19b194ee..1ceb1b262941 100644 --- a/llvm/lib/Analysis/GlobalsModRef.cpp +++ b/llvm/lib/Analysis/GlobalsModRef.cpp @@ -344,6 +344,14 @@ bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V, if (AnalyzeUsesOfPointer(I, Readers, Writers, OkayStoreDest)) return true; } else if (auto *Call = dyn_cast(I)) { + if (IntrinsicInst *II = dyn_cast(I)) { + if (II->getIntrinsicID() == Intrinsic::threadlocal_address && + V == II->getArgOperand(0)) { + if (AnalyzeUsesOfPointer(II, Readers, Writers)) + return true; + continue; + } + } // Make sure that this is just the function being called, not that it is // passing into the function. if (Call->isDataOperand(&U)) { diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index b87bba7c20e0..c038f7eaabbb 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -6255,6 +6255,10 @@ bool llvm::isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( return true; case Intrinsic::ptrmask: return !MustPreserveNullness; + case Intrinsic::threadlocal_address: + // The underlying variable changes with thread ID. The Thread ID may change + // at coroutine suspend points. + return !Call->getParent()->getParent()->isPresplitCoroutine(); default: return false; } diff --git a/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll b/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll index d109b3b8748b..24ad14be42be 100644 --- a/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll +++ b/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll @@ -22,6 +22,67 @@ entry: ret i32 %v } +@g1_tls = internal thread_local global i32 0 + +define i32 @test1_tls(ptr %param) { +; Ensure that we can fold a store to a load of a global across a store to +; a parameter when the global is non-escaping. +; +; CHECK-LABEL: define i32 @test1_tls( +; CHECK-SAME: ptr [[PARAM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls) +; CHECK-NEXT: store i32 42, ptr [[P]], align 4 +; CHECK-NEXT: store i32 7, ptr [[PARAM]], align 4 +; CHECK-NEXT: ret i32 42 +; +entry: + %p = call ptr @llvm.threadlocal.address(ptr @g1_tls) + store i32 42, ptr %p + store i32 7, ptr %param + %p2 = call ptr @llvm.threadlocal.address(ptr @g1_tls) + %v = load i32, ptr %p2 + ret i32 %v +} + +define ptr @test1_tls_noopt(ptr %coro, ptr %param) presplitcoroutine { +; CHECK-LABEL: define ptr @test1_tls_noopt( +; CHECK-SAME: ptr [[CORO:%.*]], ptr [[PARAM:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls) +; CHECK-NEXT: store i32 42, ptr [[P]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.coro.suspend(token none, i1 false) +; CHECK-NEXT: switch i8 [[TMP0]], label [[SUSPEND:%.*]] [ +; CHECK-NEXT: i8 0, label [[RESUME:%.*]] +; CHECK-NEXT: i8 1, label [[SUSPEND]] +; CHECK-NEXT: ] +; CHECK: resume: +; CHECK-NEXT: [[P2:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls) +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P2]], align 4 +; CHECK-NEXT: store i32 [[V]], ptr [[PARAM]], align 4 +; CHECK-NEXT: ret ptr [[CORO]] +; CHECK: suspend: +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.coro.end(ptr [[CORO]], i1 false, token none) +; CHECK-NEXT: ret ptr [[CORO]] +; +entry: + %p = call ptr @llvm.threadlocal.address(ptr @g1_tls) + store i32 42, ptr %p + + %0 = call i8 @llvm.coro.suspend(token none, i1 false) + switch i8 %0, label %suspend [i8 0, label %resume + i8 1, label %suspend] +resume: + %p2 = call ptr @llvm.threadlocal.address(ptr @g1_tls) + %v = load i32, ptr %p2 + store i32 %v, ptr %param, align 4 + ret ptr %coro + +suspend: + call i1 @llvm.coro.end(ptr %coro, i1 0) + ret ptr %coro +} + declare ptr @f() define i32 @test2() { diff --git a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll index 7db1048c258c..d3fa94779dd7 100644 --- a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll +++ b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll @@ -229,24 +229,24 @@ define signext i32 @test3() { ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r8, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLSv2 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r6, 2 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 1 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r5, ElementIntTLS2[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r6, ElementIntTLS3[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r7, ElementIntTLS4[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r9, ElementIntTLS5[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r8 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r7, ElementIntTLS3[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r6, 320(r5) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r5, 3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r6, ElementIntTLS4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r5, 324(r7) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r5, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLSv2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: la r7, ElementIntTLS5[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r5 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 4 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 24(r3) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 2 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 320(r5) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 3 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 324(r6) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 88 -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r7) -; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r6) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 332(r7) ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 102 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) @@ -258,26 +258,26 @@ define signext i32 @test3() { ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C3@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C3@u(r2) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r6, L..C3@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r7, 3 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r5, 2 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r4, ElementIntTLS2[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r5, 320(r4) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 1 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r5, ElementIntTLS2[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r7, ElementIntTLS3[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r8, ElementIntTLS4[TL]@ld(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r9, ElementIntTLS5[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r5, ElementIntTLS3[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r7, 324(r5) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r5, ElementIntTLS4[TL]@ld(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: la r7, ElementIntTLS5[TL]@ld(r3) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stwux r4, r3, r6 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 4 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 24(r3) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 2 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 320(r5) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 3 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 324(r7) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 88 -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 328(r8) -; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 328(r5) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 332(r7) ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 102 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 ; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) @@ -351,12 +351,12 @@ entry: ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 9, 3, 9 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 6, 3, 6 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stwux 4, 3, 5 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 2 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 320(6) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 324(7) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 4 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 24(3) -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 320(6) -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 3 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 324(7) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 88 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 328(8) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 332(9) @@ -466,12 +466,12 @@ entry: ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 9, 3, 9 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 6, 3, 6 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stwux 4, 3, 5 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 2 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 320(6) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 324(7) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 4 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 24(3) -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 320(6) -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 3 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 324(7) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 88 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 328(8) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 332(9) diff --git a/llvm/test/CodeGen/PowerPC/aix-small-local-exec-tls-largeaccess.ll b/llvm/test/CodeGen/PowerPC/aix-small-local-exec-tls-largeaccess.ll index 67d82c6908d7..91013af7a318 100644 --- a/llvm/test/CodeGen/PowerPC/aix-small-local-exec-tls-largeaccess.ll +++ b/llvm/test/CodeGen/PowerPC/aix-small-local-exec-tls-largeaccess.ll @@ -30,11 +30,11 @@ define signext i32 @StoreArrays1() { ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, mySmallLocalExecTLSv1[TL]@le(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 2 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, mySmallLocalExecTLSv1[TL]@le+24(r13) +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, (mySmallLocalExecTLS4[TL]@le+328)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, (mySmallLocalExecTLS2[TL]@le+320)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 3 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, (mySmallLocalExecTLS3[TL]@le+324)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 88 -; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, (mySmallLocalExecTLS4[TL]@le+328)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, (mySmallLocalExecTLS5[TL]@le+332)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 102 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: blr @@ -46,11 +46,11 @@ define signext i32 @StoreArrays1() { ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, mySmallLocalExecTLSv1[TL]@le(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 2 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, mySmallLocalExecTLSv1[TL]@le+24(r13) +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, (mySmallLocalExecTLS4[TL]@le+328)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS2[TL]@le+320)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 3 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS3[TL]@le+324)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 88 -; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, (mySmallLocalExecTLS4[TL]@le+328)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS5[TL]@le+332)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 102 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: blr @@ -88,16 +88,16 @@ entry: define signext i32 @StoreArrays2() { ; SMALL-LOCAL-EXEC-SMALLCM64-LABEL: StoreArrays2: ; SMALL-LOCAL-EXEC-SMALLCM64: # %bb.0: # %entry -; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: ld r4, L..C0(r2) # target-flags(ppc-tprel) @mySmallLocalExecTLSv2 +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 2 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 1 +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, (mySmallLocalExecTLS2[TL]@le+320)-65536(r13) +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 3 +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, (mySmallLocalExecTLS3[TL]@le+324)-65536(r13) +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: ld r4, L..C0(r2) # target-flags(ppc-tprel) @mySmallLocalExecTLSv2 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: add r4, r13, r4 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, 0(r4) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 4 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, 24(r4) -; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 2 -; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, (mySmallLocalExecTLS2[TL]@le+320)-65536(r13) -; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 3 -; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r4, (mySmallLocalExecTLS3[TL]@le+324)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 88 ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: stw r3, (mySmallLocalExecTLS4[TL]@le+328)-65536(r13) ; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r3, 102 @@ -106,17 +106,17 @@ define signext i32 @StoreArrays2() { ; ; SMALL-LOCAL-EXEC-LARGECM64-LABEL: StoreArrays2: ; SMALL-LOCAL-EXEC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 2 +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r4, 3 +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS2[TL]@le+320)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: addis r3, L..C0@u(r2) -; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r4, 1 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, (mySmallLocalExecTLS3[TL]@le+324)-65536(r13) +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r4, 1 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: add r3, r13, r3 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, 0(r3) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r4, 4 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, 24(r3) -; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 2 -; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS2[TL]@le+320)-65536(r13) -; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 3 -; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS3[TL]@le+324)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r3, 88 ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r4, (mySmallLocalExecTLS4[TL]@le+328)-65536(r13) ; SMALL-LOCAL-EXEC-LARGECM64-NEXT: stw r3, (mySmallLocalExecTLS5[TL]@le+332)-65536(r13) @@ -162,35 +162,35 @@ entry: ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 24(13) ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+15]]) mySmallLocalExecTLSv1[TL] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, -460(13) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+21]]) mySmallLocalExecTLS4[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, -32468(13) ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+17]]) mySmallLocalExecTLS2[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 3 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, -16464(13) ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+19]]) mySmallLocalExecTLS3[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 88 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, -460(13) -; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+21]]) mySmallLocalExecTLS4[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 15544(13) ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+23]]) mySmallLocalExecTLS5[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 102 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} blr ; DIS: 0000000000000040 (idx: [[#NFA+5]]) .StoreArrays2: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, -32468(13) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+17]]) mySmallLocalExecTLS2[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+13]]) mySmallLocalExecTLSv2[TE] -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 1 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 0(3) ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+13]]) mySmallLocalExecTLSv2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, -16464(13) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+19]]) mySmallLocalExecTLS3[TL] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 1 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 13, 3 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 0(3) ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 4 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 24(3) -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, -32468(13) -; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+17]]) mySmallLocalExecTLS2[TL] -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 3 -; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, -16464(13) -; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+19]]) mySmallLocalExecTLS3[TL] ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 88 ; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, -460(13) ; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TLS_LE (idx: [[#NFA+21]]) mySmallLocalExecTLS4[TL] @@ -227,4 +227,4 @@ entry: ; DIS: 000000000000be6c (idx: [[#NFA+19]]) mySmallLocalExecTLS3[TL]: ; DIS: 000000000000fcec (idx: [[#NFA+21]]) mySmallLocalExecTLS4[TL]: ; DIS: 0000000000013b6c (idx: [[#NFA+23]]) mySmallLocalExecTLS5[TL]: -; DIS: 00000000000179ec (idx: [[#NFA+25]]) mySmallLocalExecTLSv2[TL]: \ No newline at end of file +; DIS: 00000000000179ec (idx: [[#NFA+25]]) mySmallLocalExecTLSv2[TL]: diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll index 38b35dc6c81c..91a2283897f3 100644 --- a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll @@ -64,9 +64,9 @@ define i64 @StoreLargeAccess2() { ; 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: add r3, r13, r5 +; CHECK-SMALLCM64-NEXT: std r4, 20000(r3) ; 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 @@ -75,8 +75,8 @@ define i64 @StoreLargeAccess2() { ; 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: li r4, 55 ; 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 diff --git a/llvm/test/CodeGen/X86/threadlocal_address.ll b/llvm/test/CodeGen/X86/threadlocal_address.ll index 6c6649b6419c..52ff413e6988 100644 --- a/llvm/test/CodeGen/X86/threadlocal_address.ll +++ b/llvm/test/CodeGen/X86/threadlocal_address.ll @@ -4,7 +4,7 @@ define noundef i32 @foo() { ; CHECK: %0:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load (s64) from got) -; CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $fs :: (load (s32) from %ir.0) +; CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $fs :: (dereferenceable load (s32) from %ir.0) ; CHECK: %2:gr32 = nsw INC32r %1, implicit-def dead $eflags ; CHECK: MOV32mr %0, 1, $noreg, 0, $fs, %2 :: (store (s32) into %ir.0) ; CHECK: $eax = COPY %2 @@ -22,7 +22,7 @@ entry: @j = thread_local addrspace(1) global ptr addrspace(0) @i, align 4 define noundef i32 @bar() { ; CHECK: %0:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @j, $noreg :: (load (s64) from got) -; CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $fs :: (load (s32) from %ir.0, addrspace 1) +; CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $fs :: (dereferenceable load (s32) from %ir.0, addrspace 1) ; CHECK: %2:gr32 = nsw INC32r %1, implicit-def dead $eflags ; CHECK: MOV32mr %0, 1, $noreg, 0, $fs, %2 :: (store (s32) into %ir.0, addrspace 1) ; CHECK: $eax = COPY %2 -- GitLab From ab22504479cb7b8985855aa2f2c851390bc1d167 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 19 Apr 2024 13:20:36 -0400 Subject: [PATCH 025/357] [libc++] Fix usage of 'exclude_from_explicit_instantiation' attribute on local class members (#89377) #88777 adds a warning for when the `exclude_from_explicit_instantiation` attribute is applied to local classes and members thereof. This patch addresses the few instances of `exclude_from_explicit_instantiation` being applied to local class members in libc++. --- libcxx/include/__memory/uses_allocator_construction.h | 8 +++----- libcxx/include/variant | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h index 9b7262bec5cf..5e5819d4c281 100644 --- a/libcxx/include/__memory/uses_allocator_construction.h +++ b/libcxx/include/__memory/uses_allocator_construction.h @@ -184,20 +184,18 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Type&& __value) noexc struct __pair_constructor { using _PairMutable = remove_cv_t<_Pair>; - _LIBCPP_HIDE_FROM_ABI constexpr auto __do_construct(const _PairMutable& __pair) const { + _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const { return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair); } - _LIBCPP_HIDE_FROM_ABI constexpr auto __do_construct(_PairMutable&& __pair) const { + _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const { return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair)); } const _Alloc& __alloc_; _Type& __value_; - _LIBCPP_HIDE_FROM_ABI constexpr operator _PairMutable() const { - return __do_construct(std::forward<_Type>(this->__value_)); - } + _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); } }; return std::make_tuple(__pair_constructor{__alloc, __value}); diff --git a/libcxx/include/variant b/libcxx/include/variant index 1b5e84e95479..858a49b980bd 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -909,8 +909,8 @@ protected: __a.__value = std::forward<_Arg>(__arg); } else { struct { - _LIBCPP_HIDE_FROM_ABI void operator()(true_type) const { __this->__emplace<_Ip>(std::forward<_Arg>(__arg)); } - _LIBCPP_HIDE_FROM_ABI void operator()(false_type) const { + _LIBCPP_HIDDEN void operator()(true_type) const { __this->__emplace<_Ip>(std::forward<_Arg>(__arg)); } + _LIBCPP_HIDDEN void operator()(false_type) const { __this->__emplace<_Ip>(_Tp(std::forward<_Arg>(__arg))); } __assignment* __this; -- GitLab From c045955501ed28fee7c40d8822a1aacc2022786e Mon Sep 17 00:00:00 2001 From: Rob Suderman Date: Fri, 19 Apr 2024 10:36:09 -0700 Subject: [PATCH 026/357] [mlir][tensor] Fold `tensor.reshape` for dynamic reshape (#88961) If `tensor.reshape` occurs with `d0, d1, d2, ...` for the dimensions we know that the reshape is a no-op. Checking for this case lets us fold away the computation. --- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 35 ++++++++++++++++ mlir/test/Dialect/Tensor/canonicalize.mlir | 47 ++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index 80bc04d62bbe..3ff41ab22fbc 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -1580,6 +1580,41 @@ OpFoldResult ReshapeOp::fold(FoldAdaptor adaptor) { llvm::dyn_cast_if_present(adaptor.getSource()), getResult().getType())) return reshapedSource; + + auto source = getSource(); + auto sourceTy = dyn_cast(source.getType()); + auto resultTy = dyn_cast(getType()); + + if (!sourceTy || !resultTy || sourceTy != resultTy) + return {}; + + if (auto fromElements = getShape().getDefiningOp()) { + auto elements = fromElements.getElements(); + bool dynamicNoop = + sourceTy.getRank() == static_cast(elements.size()); + for (int id = 0, s = elements.size(); id < s && dynamicNoop; ++id) { + auto element = elements[id]; + + if (auto cst = getConstantIntValue(element)) { + dynamicNoop &= cst.value() == sourceTy.getDimSize(id); + continue; + } + + if (auto dimOp = element.getDefiningOp()) { + dynamicNoop &= dimOp.getSource() == source; + + APSInt dim; + auto cst = getConstantIntValue(dimOp.getIndex()); + dynamicNoop &= + cst.has_value() && cst.value() == static_cast(id); + continue; + } + } + + if (dynamicNoop) + return source; + } + return {}; } diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index ac365c9d297e..751c57eacd7a 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -2403,6 +2403,53 @@ func.func @dim_of_reshape_undominated(%arg0: tensor<*xf32>, %arg1: tensor +func.func @reshape_fold_2d(%arg0 : tensor) -> tensor { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %d0 = tensor.dim %arg0, %c0 : tensor + %d1 = tensor.dim %arg0, %c1 : tensor + %ds = tensor.from_elements %d0, %d1 : tensor<2xindex> + %reshape = tensor.reshape %arg0(%ds) : (tensor, tensor<2xindex>) -> tensor + // CHECK: return %[[ARG0]] + return %reshape : tensor +} + +// ----- + +// CHECK-LABEL: @reshape_nofold_2d +// CHECK-SAME: %[[ARG0:.+]]: tensor +func.func @reshape_nofold_2d(%arg0 : tensor) -> tensor { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %d0 = tensor.dim %arg0, %c0 : tensor + %d1 = tensor.dim %arg0, %c1 : tensor + %ds = tensor.from_elements %d1, %d0 : tensor<2xindex> + // CHECK: tensor.reshape + %reshape = tensor.reshape %arg0(%ds) : (tensor, tensor<2xindex>) -> tensor + return %reshape : tensor +} + + +// ----- + +// CHECK-LABEL: @reshape_fold_3d_cst +// CHECK-SAME: %[[ARG0:.+]]: tensor<5x?x?xi32> +func.func @reshape_fold_3d_cst(%arg0 : tensor<5x?x?xi32>) -> tensor<5x?x?xi32> { + %c1 = arith.constant 1 : index + %c2 = arith.constant 2 : index + %d0 = arith.constant 5 : index + %d1 = tensor.dim %arg0, %c1 : tensor<5x?x?xi32> + %d2 = tensor.dim %arg0, %c2 : tensor<5x?x?xi32> + %ds = tensor.from_elements %d0, %d1, %d2 : tensor<3xindex> + %reshape = tensor.reshape %arg0(%ds) : (tensor<5x?x?xi32>, tensor<3xindex>) -> tensor<5x?x?xi32> + // CHECK: return %[[ARG0]] + return %reshape : tensor<5x?x?xi32> +} + +// ----- + // Test case: This test fails to fold because the index of tensor.dim is out_of_bounds // CHECK-LABEL: func @dim_out_of_bounds( // CHECK: %[[IDX:.*]] = index.constant 28 -- GitLab From 4841d70a4b7d7cd8c492c16a9da339ec75bca135 Mon Sep 17 00:00:00 2001 From: Michael Klemm Date: Fri, 19 Apr 2024 19:44:53 +0200 Subject: [PATCH 027/357] [flang] Remove obsolete flang-to-external-fc tool (#88904) It seems like the `flang-to-external-fc` tool is no longer needed, because Flang is now a full compiler in its own right. After PR #85249 has landed, this tool will not be able to pick up the `.f18.mod` files. --- flang/docs/FlangDriver.md | 20 - flang/tools/f18/CMakeLists.txt | 11 - flang/tools/f18/flang-to-external-fc.in | 497 ------------------------ 3 files changed, 528 deletions(-) delete mode 100755 flang/tools/f18/flang-to-external-fc.in diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index 814f3eb12cfc..ac120b4ff09b 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -266,26 +266,6 @@ is `ParseSyntaxOnlyAction`, which corresponds to `-fsyntax-only`. In other words, `flang-new -fc1 ` is equivalent to `flang-new -fc1 -fsyntax-only `. -## The `flang-to-external-fc` script -The `flang-to-external-fc` wrapper script for `flang-new` was introduced as a -development tool and to facilitate testing. The `flang-to-external-fc` wrapper -script will: -* use `flang-new` to unparse the input source file (i.e. it will run `flang-new - -fc1 -fdebug-unparse `), and then -* call a host Fortran compiler, e.g. `gfortran`, to compile the unparsed file. - -Here's a basic breakdown of what happens inside `flang-to-external-fc` when you -run `flang-to-external-fc file.f90`: -```bash -flang-new -fc1 -fdebug-unparse file.f90 -o file-unparsed.f90 -gfortran file-unparsed.f90 -``` -This is a simplified version for illustration purposes only. In practice, -`flang-to-external-fc` adds a few more frontend options and it also supports -various other use cases (e.g. compiling C files, linking existing object -files). `gfortran` is the default host compiler used by `flang-to-external-fc`. -You can change it by setting the `FLANG_FC` environment variable. - ## Adding new Compiler Options Adding a new compiler option in Flang consists of two steps: * define the new option in a dedicated TableGen file, diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index dda3b6887be8..64815a1f5da6 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -93,17 +93,6 @@ endif() add_custom_target(module_files ALL DEPENDS ${MODULE_FILES}) -# This flang shell script will only work in a POSIX shell. -if (NOT WIN32) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/flang-to-external-fc.in - ${CMAKE_BINARY_DIR}/bin/flang-to-external-fc - @ONLY - ) - add_custom_target(flang-to-external-fc ALL DEPENDS ${CMAKE_BINARY_DIR}/bin/flang-to-external-fc) - install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/flang-to-external-fc DESTINATION "${CMAKE_INSTALL_BINDIR}") -endif() - # TODO Move this to a more suitable location # Copy the generated omp_lib.h header file, if OpenMP support has been configured. if (LLVM_TOOL_OPENMP_BUILD) diff --git a/flang/tools/f18/flang-to-external-fc.in b/flang/tools/f18/flang-to-external-fc.in deleted file mode 100755 index bd16c030121c..000000000000 --- a/flang/tools/f18/flang-to-external-fc.in +++ /dev/null @@ -1,497 +0,0 @@ -#! /usr/bin/env bash -#===-- tools/f18/flang-to-external-fc.sh --------------------------*- sh -*-===# -# -# 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 -# -#===------------------------------------------------------------------------===# -# A wrapper script for Flang's compiler driver that was developed for testing and -# experimenting. You should be able to use it as a regular compiler driver. It -# will: -# * run Flang's compiler driver to unparse the input source files -# * use the external compiler (defined via FLANG_FC environment variable) to -# compile the unparsed source files -# -# Tested with Bash 4.4. This script will exit immediately if you use an -# older version of Bash. -#===------------------------------------------------------------------------===# -set -euo pipefail - -# Global variables to make the parsing of input arguments a bit easier -INPUT_FILES=() -OPTIONS=() -OUTPUT_FILE="" -MODULE_DIR="" -INTRINSICS_MOD_DIR="" -COMPILE_ONLY="False" -PREPROCESS_ONLY="False" -PRINT_VERSION="False" - -# === check_bash_version ====================================================== -# -# Checks the Bash version that's used to run this script. Exits immediately -# with a non-zero return code if it's lower than 4.4. Otherwise returns 0 -# (success). -# ============================================================================= -check_bash_version() { - message="Error: Your Bash is too old. Please use Bash >= 4.4" - # Major version - [[ "${BASH_VERSINFO[0]:-0}" -lt 4 ]] && echo $message && exit 1 - - # Minor version - if [[ "${BASH_VERSINFO[0]}" == 4 ]]; then - [[ "${BASH_VERSINFO[1]:-0}" -lt 4 ]] && echo $message && exit 1 - fi - - return 0 -} - -# === parse_args ============================================================== -# -# Parse the input arguments passed to this script. Sets the global variables -# declared at the top. -# -# INPUTS: -# $1 - all input arguments -# OUTPUTS: -# Saved in the global variables for this script -# ============================================================================= -parse_args() -{ - while [ "${1:-}" != "" ]; do - # CASE 1: Compiler option - if [[ "${1:0:1}" == "-" ]] ; then - # Output file - extract it into a global variable - if [[ "$1" == "-o" ]] ; then - shift - OUTPUT_FILE="$1" - shift - continue - fi - - # Module directory - extract it into a global variable - if [[ "$1" == "-module-dir" ]]; then - shift - MODULE_DIR="$1" - shift - continue - fi - - # Intrinsics module dir - extract it into a global var - if [[ "$1" == "-intrinsics-module-directory" ]]; then shift - INTRINSICS_MOD_DIR=$1 - shift - continue - fi - - # Module suffix cannot be modified - this script defines it before - # calling the driver. - if [[ "$1" == "-module-suffix" ]]; then - echo "ERROR: \'-module-suffix\' is not available when using the \'flang\' script" - exit 1 - fi - - # Special treatment for `J ` and `-I `. We translate these - # into `J` and `-I` respectively. - if [[ "$1" == "-J" ]] || [[ "$1" == "-I" ]]; then - opt=$1 - shift - OPTIONS+=("$opt$1") - shift - continue - fi - - # This is a regular option - just add it to the list. - OPTIONS+=($1) - if [[ $1 == "-c" ]]; then - COMPILE_ONLY="True" - fi - - if [[ $1 == "-S" ]]; then - COMPILE_ONLY="True" - fi - - if [[ $1 == "-E" ]]; then - PREPROCESS_ONLY="True" - fi - - if [[ $1 == "-v" || $1 == "--version" ]]; then - PRINT_VERSION="True" - fi - - shift - continue - - # CASE 2: A regular file (either source or a library file) - elif [[ -f "$1" ]]; then - INPUT_FILES+=($1) - shift - continue - - else - # CASE 3: Unsupported - echo "ERROR: unrecognised option format: \`$1\`. Perhaps non-existent file?" - exit 1 - fi - done -} - -# === categorise_files ======================================================== -# -# Categorises input files into: -# * Fortran source files (to be compiled) -# * library files (to be linked into the final executable) -# -# INPUTS: -# $1 - all input files to be categorised (array, name reference) -# OUTPUTS: -# $2 - Fortran source files extracted from $1 (array, name reference) -# $3 - other source files extracted from $1 (array, name reference) -# $4 - object files extracted from $1 (array, name reference) -# $5 - lib files extracted from $1 (array, name reference) -# ============================================================================= -categorise_files() -{ - local -n -r all_files=$1 - local -n fortran_sources=$2 - local -n other_sources=$3 - local -n objects=$4 - local -n libs=$5 - - for current_file in "${all_files[@]}"; do - file_ext=${current_file##*.} - if [[ $file_ext == "f" ]] || [[ $file_ext == "f90" ]] || - [[ $file_ext == "f" ]] || [[ $file_ext == "F" ]] || [[ $file_ext == "ff" ]] || - [[ $file_ext == "f90" ]] || [[ $file_ext == "F90" ]] || [[ $file_ext == "ff90" ]] || - [[ $file_ext == "f95" ]] || [[ $file_ext == "F95" ]] || [[ $file_ext == "ff95" ]] || - [[ $file_ext == "cuf" ]] || [[ $file_ext == "CUF" ]] || [[ $file_ext == "f18" ]] || - [[ $file_ext == "F18" ]] || [[ $file_ext == "ff18" ]]; then - fortran_sources+=($current_file) - elif [[ $file_ext == "a" ]] || [[ $file_ext == "so" ]]; then - libs+=($current_file) - elif [[ $file_ext == "o" ]]; then - objects+=($current_file) - else - other_sources+=($current_file) - fi - done -} - -# === categorise_opts ========================================================== -# -# Categorises compiler options into options for: -# * the Flang driver (either new or the "throwaway" driver) -# * the external Fortran driver that will generate the code -# Most options accepted by Flang will be claimed by it. The only exceptions are -# `-I` and `-J`. -# -# INPUTS: -# $1 - all compiler options (array, name reference) -# OUTPUTS: -# $2 - compiler options for the Flang driver (array, name reference) -# $3 - compiler options for the external driver (array, name reference) -# ============================================================================= -categorise_opts() -{ - local -n all_opts=$1 - local -n flang_opts=$2 - local -n fc_opts=$3 - - for opt in "${all_opts[@]}"; do - # These options are claimed by Flang, but should've been dealt with in parse_args. - if [[ $opt == "-module-dir" ]] || - [[ $opt == "-o" ]] || - [[ $opt == "-fintrinsic-modules-path" ]] ; then - echo "ERROR: $opt should've been fully processed by \`parse_args\`" - exit 1 - fi - - if - # The options claimed by Flang. This list needs to be compatible with - # what's supported by Flang's compiler driver (i.e. `flang-new`). - [[ $opt == "-cpp" ]] || - [[ $opt =~ ^-D.* ]] || - [[ $opt == "-E" ]] || - [[ $opt == "-falternative-parameter-statement" ]] || - [[ $opt == "-fbackslash" ]] || - [[ $opt == "-fcolor-diagnostics" ]] || - [[ $opt == "-fdefault-double-8" ]] || - [[ $opt == "-fdefault-integer-8" ]] || - [[ $opt == "-fdefault-real-8" ]] || - [[ $opt == "-ffixed-form" ]] || - [[ $opt =~ ^-ffixed-line-length=.* ]] || - [[ $opt == "-ffree-form" ]] || - [[ $opt == "-fimplicit-none" ]] || - [[ $opt =~ ^-finput-charset=.* ]] || - [[ $opt == "-flarge-sizes" ]] || - [[ $opt == "-flogical-abbreviations" ]] || - [[ $opt == "-fno-color-diagnostics" ]] || - [[ $opt == "-fxor-operator" ]] || - [[ $opt == "-help" ]] || - [[ $opt == "-nocpp" ]] || - [[ $opt == "-pedantic" ]] || - [[ $opt =~ ^-std=.* ]] || - [[ $opt =~ ^-U.* ]] || - [[ $opt == "-Werror" ]]; then - flang_opts+=($opt) - elif - # We translate the following into equivalents understood by `flang-new` - [[ $opt == "-Mfixed" ]] || [[ $opt == "-Mfree" ]]; then - case $opt in - -Mfixed) - flang_opts+=("-ffixed-form") - ;; - - -Mfree) - flang_opts+=("-ffree-form") - ;; - - *) - echo "ERROR: $opt has no equivalent in 'flang-new'" - exit 1 - ;; - esac - elif - # Options that are needed for both Flang and the external driver. - [[ $opt =~ -I.* ]] || - [[ $opt =~ -J.* ]] || - [[ $opt == "-fopenmp" ]] || - [[ $opt == "-fopenacc" ]]; then - flang_opts+=($opt) - fc_opts+=($opt) - else - # All other options are claimed for the external driver. - fc_opts+=($opt) - fi - done -} - -# === get_external_fc_name ==================================================== -# -# Returns the name of external Fortran compiler based on values of -# environment variables. -# ============================================================================= -get_external_fc_name() { - if [[ -v FLANG_FC ]]; then - echo ${FLANG_FC} - elif [[ -v F18_FC ]]; then - # We support F18_FC for backwards compatibility. - echo ${F18_FC} - else - echo gfortran - fi -} - -# === preprocess ============================================================== -# -# Runs the preprocessing. Fortran files are preprocessed using Flang. Other -# files are preprocessed using the external Fortran compiler. -# -# INPUTS: -# $1 - Fortran source files (array, name reference) -# $2 - other source files (array, name reference) -# $3 - compiler flags (array, name reference) -# ============================================================================= -preprocess() { - local -n fortran_srcs=$1 - local -n other_srcs=$2 - local -n opts=$3 - - local ext_fc="$(get_external_fc_name)" - - local -r wd=$(cd "$(dirname "$0")/.." && pwd) - - # Use the provided output file name. - if [[ ! -z ${OUTPUT_FILE:+x} ]]; then - output_definition="-o $OUTPUT_FILE" - fi - - # Preprocess fortran sources using Flang - for idx in "${!fortran_srcs[@]}"; do - if ! "$wd/bin/flang-new" -E "${opts[@]}" "${fortran_srcs[$idx]}" ${output_definition:+$output_definition} - then status=$? - echo flang: in "$PWD", flang-new failed with exit status $status: "$wd/bin/flang-new" "${opts[@]}" "$@" >&2 - exit $status - fi - done - - # Preprocess other sources using Flang - for idx in "${!other_srcs[@]}"; do - if ! $ext_fc -E "${opts[@]}" "${other_srcs[$idx]}" ${output_definition:+$output_definition} - then status=$? - echo flang: in "$PWD", flang-new failed with exit status $status: "$wd/bin/flang-new" "${opts[@]}" "$@" >&2 - exit $status - fi - done -} - -# === get_relocatable_name ====================================================== -# This method generates the name of the output file for the compilation phase -# (triggered with `-c`). If the user of this script is only interested in -# compilation (`flang -c`), use $OUTPUT_FILE provided that it was defined. -# Otherwise, use the usual heuristics: -# * file.f --> file.o -# * file.c --> file.o -# -# INPUTS: -# $1 - input source file for which to generate the output name -# ============================================================================= -get_relocatable_name() { - local -r src_file=$1 - - if [[ $COMPILE_ONLY == "True" ]] && [[ ! -z ${OUTPUT_FILE:+x} ]]; then - out_file="$OUTPUT_FILE" - else - current_ext=${src_file##*.} - new_ext="o" - - out_file=$(basename "${src_file}" "$current_ext")${new_ext} - fi - - echo "$out_file" -} - -# === main ==================================================================== -# Main entry point for this script -# ============================================================================= -main() { - check_bash_version - parse_args "$@" - - if [[ $PRINT_VERSION == "True" ]]; then - echo "flang version @FLANG_VERSION@" - exit 0 - fi - - # Source, object and library files provided by the user - local fortran_source_files=() - local other_source_files=() - local object_files=() - local lib_files=() - categorise_files INPUT_FILES fortran_source_files other_source_files object_files lib_files - - if [[ $PREPROCESS_ONLY == "True" ]]; then - preprocess fortran_source_files other_source_files OPTIONS - exit 0 - fi - - # Options for the Flang driver. - # NOTE: We need `-fc1` to make sure that the frontend driver rather than - # compiler driver is used. We also need to make sure that that's the first - # flag that the driver will see (otherwise it assumes compiler/toolchain - # driver mode). - local flang_options=("-fc1") - # Options for the external Fortran Compiler - local ext_fc_options=() - categorise_opts OPTIONS flang_options ext_fc_options - - local -r wd=$(cd "$(dirname "$0")/.." && pwd) - - # uuidgen is common but not installed by default on some distros - if ! command -v uuidgen &> /dev/null - then - echo "uuidgen is required for generating unparsed file names." - exit 1 - fi - - # STEP 1: Unparse - # Base-name for the unparsed files. These are just temporary files that are - # first generated and then deleted by this script. - # NOTE: We need to make sure that the base-name is unique to every - # invocation. Otherwise we can't use this script in parallel. - local -r unique_id=$(uuidgen | cut -b25-36) - local -r unparsed_file_base="flang_unparsed_file_$unique_id" - - flang_options+=("-module-suffix") - flang_options+=(".f18.mod") - flang_options+=("-fdebug-unparse") - flang_options+=("-fno-analyzed-objects-for-unparse") - - [[ ! -z ${MODULE_DIR} ]] && flang_options+=("-module-dir ${MODULE_DIR}") - [[ ! -z ${INTRINSICS_MOD_DIR} ]] && flang_options+=("-intrinsics-module-directory ${INTRINSICS_MOD_DIR}") - for idx in "${!fortran_source_files[@]}"; do - set +e - "$wd/bin/flang-new" "${flang_options[@]}" "${fortran_source_files[$idx]}" -o "${unparsed_file_base}_${idx}.f90" - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", flang-new failed with exit status "$ret_status": "$wd/bin/flang-new" "${flang_options[@]}" "$@" >&2 - exit "$ret_status" - fi - done - - # STEP 2: Compile Fortran Source Files - local ext_fc="$(get_external_fc_name)" - # Temporary object files generated by this script. To be deleted at the end. - local temp_object_files=() - for idx in "${!fortran_source_files[@]}"; do - # We always have to specify the output name with `-o `. This - # is because we are using the unparsed rather than the original source file - # below. As a result, we cannot rely on the compiler-generated output name. - out_obj_file=$(get_relocatable_name "${fortran_source_files[$idx]}") - - set +e - $ext_fc "-c" "${ext_fc_options[@]}" "${unparsed_file_base}_${idx}.f90" "-o" "${out_obj_file}" - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit "$ret_status" - fi - temp_object_files+=(${out_obj_file}) - done - - # Delete the unparsed files - for idx in "${!fortran_source_files[@]}"; do - rm "${unparsed_file_base}_${idx}.f90" - done - - # STEP 3: Compile Other Source Files - for idx in "${!other_source_files[@]}"; do - # We always specify the output name with `-o `. The user - # might have used `-o`, but we never add it to $OPTIONS (or - # $ext_fc_options). Hence we need to use `get_relocatable_name`. - out_obj_file=$(get_relocatable_name "${other_source_files[$idx]}") - - set +e - $ext_fc "-c" "${ext_fc_options[@]}" "${other_source_files[${idx}]}" "-o" "${out_obj_file}" - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit "$ret_status" - fi - temp_object_files+=(${out_obj_file}) - done - - # STEP 4: Link - if [[ $COMPILE_ONLY == "True" ]]; then - exit 0; - fi - - if [[ ${#temp_object_files[@]} -ge 1 ]] || [[ ${#object_files[@]} -ge 1 ]] ; then - # If $OUTPUT_FILE was specified, use it for the output name. - if [[ ! -z ${OUTPUT_FILE:+x} ]]; then - output_definition="-o $OUTPUT_FILE" - else - output_definition="" - fi - - set +e - $ext_fc "${ext_fc_options[@]}" "${object_files[@]}" "${temp_object_files[@]}" "${lib_files[@]}" ${output_definition:+$output_definition} - ret_status=$? - set -e - if [[ $ret_status != 0 ]]; then - echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit "$ret_status" - fi - fi - - # Delete intermediate object files - for idx in "${!fortran_source_files[@]}"; do - rm "${temp_object_files[$idx]}" - done -} - -main "${@}" -- GitLab From a6a4d4a0949fa7aab93429754704f28505d56d3f Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Fri, 19 Apr 2024 08:51:26 -0700 Subject: [PATCH 028/357] Reland "[flang][build] Fixed paths discrovery for the out-of-tree build. (#87822)" This reverts commit 215eee60497489ae0cc7cc78c0d8b8270e057a70. --- flang/CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 71141e5efac4..c8e75024823f 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -81,12 +81,13 @@ if (FLANG_STANDALONE_BUILD) mark_as_advanced(LLVM_ENABLE_ASSERTIONS) endif() - # We need a pre-built/installed version of LLVM. - find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}") # If the user specifies a relative path to LLVM_DIR, the calls to include # LLVM modules fail. Append the absolute path to LLVM_DIR instead. - get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} REALPATH) + get_filename_component(LLVM_DIR_ABSOLUTE ${LLVM_DIR} + REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR_ABSOLUTE}) + # We need a pre-built/installed version of LLVM. + find_package(LLVM REQUIRED HINTS "${LLVM_DIR_ABSOLUTE}") # Users might specify a path to CLANG_DIR that's: # * a full path, or @@ -97,7 +98,7 @@ if (FLANG_STANDALONE_BUILD) CLANG_DIR_ABSOLUTE ${CLANG_DIR} REALPATH - ${CMAKE_CURRENT_SOURCE_DIR}) + BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${CLANG_DIR_ABSOLUTE}) # TODO: Remove when libclangDriver is lifted out of Clang @@ -124,13 +125,14 @@ if (FLANG_STANDALONE_BUILD) include(AddClang) include(TableGen) - find_package(MLIR REQUIRED CONFIG) - # Use SYSTEM for the same reasons as for LLVM includes - include_directories(SYSTEM ${MLIR_INCLUDE_DIRS}) # If the user specifies a relative path to MLIR_DIR, the calls to include # MLIR modules fail. Append the absolute path to MLIR_DIR instead. - get_filename_component(MLIR_DIR_ABSOLUTE ${MLIR_DIR} REALPATH) + get_filename_component(MLIR_DIR_ABSOLUTE ${MLIR_DIR} + REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${MLIR_DIR_ABSOLUTE}) + find_package(MLIR REQUIRED CONFIG HINTS ${MLIR_DIR_ABSOLUTE}) + # Use SYSTEM for the same reasons as for LLVM includes + include_directories(SYSTEM ${MLIR_INCLUDE_DIRS}) include(AddMLIR) find_program(MLIR_TABLEGEN_EXE "mlir-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) -- GitLab From afc8ad0d938b3fa74e92f1d066d28e64a7f7f905 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 19 Apr 2024 17:52:39 +0100 Subject: [PATCH 029/357] [X86] LowerFunnelShift - improve handling of vXi8 constant splat funnel shifts This patch moves the promotion to vXi16 shifts and the upper/lower bit masking into LowerFunnelShift for targets that have a bit-select instruction (XOP's VPCMOV and AVX512's VPTERNLOG). This prevents the regressions in #89115 due to the masking of ((X << V) | (Y >> (8-V))) vXi8 shifts. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 25 +++++++++++++++++++++++- llvm/test/CodeGen/X86/vector-fshl-128.ll | 6 +++--- llvm/test/CodeGen/X86/vector-fshl-256.ll | 20 +++++++++---------- llvm/test/CodeGen/X86/vector-fshr-128.ll | 6 +++--- llvm/test/CodeGen/X86/vector-fshr-256.ll | 20 +++++++++---------- 5 files changed, 48 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index bedec0c8974a..3a51c7c2ca85 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -29830,6 +29830,7 @@ static SDValue LowerFunnelShift(SDValue Op, const X86Subtarget &Subtarget, if (VT.isVector()) { APInt APIntShiftAmt; bool IsCstSplat = X86::isConstantSplat(Amt, APIntShiftAmt); + unsigned NumElts = VT.getVectorNumElements(); if (Subtarget.hasVBMI2() && EltSizeInBits > 8) { if (IsFSHR) @@ -29858,6 +29859,29 @@ static SDValue LowerFunnelShift(SDValue Op, const X86Subtarget &Subtarget, uint64_t ShiftAmt = APIntShiftAmt.urem(EltSizeInBits); uint64_t ShXAmt = IsFSHR ? (EltSizeInBits - ShiftAmt) : ShiftAmt; uint64_t ShYAmt = IsFSHR ? ShiftAmt : (EltSizeInBits - ShiftAmt); + assert((ShXAmt + ShYAmt) == EltSizeInBits && "Illegal funnel shift"); + + if (EltSizeInBits == 8 && ShXAmt > 1 && + (Subtarget.hasXOP() || useVPTERNLOG(Subtarget, VT))) { + // For vXi8 cases on Subtargets that can perform VPCMOV/VPTERNLOG + // bit-select - lower using vXi16 shifts and then perform the bitmask at + // the original vector width to handle cases where we split. + MVT WideVT = MVT::getVectorVT(MVT::i16, NumElts / 2); + APInt MaskX = APInt::getHighBitsSet(8, 8 - ShXAmt); + APInt MaskY = APInt::getLowBitsSet(8, 8 - ShYAmt); + SDValue ShX = + DAG.getNode(ISD::SHL, DL, WideVT, DAG.getBitcast(WideVT, Op0), + DAG.getShiftAmountConstant(ShXAmt, WideVT, DL)); + SDValue ShY = + DAG.getNode(ISD::SRL, DL, WideVT, DAG.getBitcast(WideVT, Op1), + DAG.getShiftAmountConstant(ShYAmt, WideVT, DL)); + ShX = DAG.getNode(ISD::AND, DL, VT, DAG.getBitcast(VT, ShX), + DAG.getConstant(MaskX, DL, VT)); + ShY = DAG.getNode(ISD::AND, DL, VT, DAG.getBitcast(VT, ShY), + DAG.getConstant(MaskY, DL, VT)); + return DAG.getNode(ISD::OR, DL, VT, ShX, ShY); + } + SDValue ShX = DAG.getNode(ISD::SHL, DL, VT, Op0, DAG.getShiftAmountConstant(ShXAmt, VT, DL)); SDValue ShY = DAG.getNode(ISD::SRL, DL, VT, Op1, @@ -29874,7 +29898,6 @@ static SDValue LowerFunnelShift(SDValue Op, const X86Subtarget &Subtarget, return SDValue(); unsigned ShiftOpc = IsFSHR ? ISD::SRL : ISD::SHL; - unsigned NumElts = VT.getVectorNumElements(); MVT ExtSVT = MVT::getIntegerVT(2 * EltSizeInBits); MVT ExtVT = MVT::getVectorVT(ExtSVT, NumElts / 2); diff --git a/llvm/test/CodeGen/X86/vector-fshl-128.ll b/llvm/test/CodeGen/X86/vector-fshl-128.ll index 1addedf3c3d9..0459d47eed81 100644 --- a/llvm/test/CodeGen/X86/vector-fshl-128.ll +++ b/llvm/test/CodeGen/X86/vector-fshl-128.ll @@ -2453,9 +2453,9 @@ define <16 x i8> @splatconstant_funnnel_v16i8(<16 x i8> %x, <16 x i8> %y) nounwi ; ; XOP-LABEL: splatconstant_funnnel_v16i8: ; XOP: # %bb.0: -; XOP-NEXT: vpshlb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 -; XOP-NEXT: vpshlb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; XOP-NEXT: vpor %xmm1, %xmm0, %xmm0 +; XOP-NEXT: vpsrlw $4, %xmm1, %xmm1 +; XOP-NEXT: vpsllw $4, %xmm0, %xmm0 +; XOP-NEXT: vpcmov {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0, %xmm0 ; XOP-NEXT: retq ; ; X86-SSE2-LABEL: splatconstant_funnnel_v16i8: diff --git a/llvm/test/CodeGen/X86/vector-fshl-256.ll b/llvm/test/CodeGen/X86/vector-fshl-256.ll index ebcb1cb15a60..e81b9adfdd3e 100644 --- a/llvm/test/CodeGen/X86/vector-fshl-256.ll +++ b/llvm/test/CodeGen/X86/vector-fshl-256.ll @@ -2344,17 +2344,15 @@ define <32 x i8> @splatconstant_funnnel_v32i8(<32 x i8> %x, <32 x i8> %y) nounwi ; ; XOPAVX1-LABEL: splatconstant_funnnel_v32i8: ; XOPAVX1: # %bb.0: -; XOPAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 -; XOPAVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm2, %xmm2 -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm1, %xmm1 -; XOPAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 -; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 -; XOPAVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4] -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm2, %xmm2 -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm0, %xmm0 -; XOPAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 -; XOPAVX1-NEXT: vorps %ymm1, %ymm0, %ymm0 +; XOPAVX1-NEXT: vpsrlw $4, %xmm1, %xmm2 +; XOPAVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; XOPAVX1-NEXT: vpsrlw $4, %xmm1, %xmm1 +; XOPAVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; XOPAVX1-NEXT: vpsllw $4, %xmm0, %xmm2 +; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; XOPAVX1-NEXT: vpsllw $4, %xmm0, %xmm0 +; XOPAVX1-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 +; XOPAVX1-NEXT: vpcmov {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0, %ymm0 ; XOPAVX1-NEXT: retq ; ; XOPAVX2-LABEL: splatconstant_funnnel_v32i8: diff --git a/llvm/test/CodeGen/X86/vector-fshr-128.ll b/llvm/test/CodeGen/X86/vector-fshr-128.ll index 638a3cdaa2c1..b839452725a9 100644 --- a/llvm/test/CodeGen/X86/vector-fshr-128.ll +++ b/llvm/test/CodeGen/X86/vector-fshr-128.ll @@ -2462,9 +2462,9 @@ define <16 x i8> @splatconstant_funnnel_v16i8(<16 x i8> %x, <16 x i8> %y) nounwi ; ; XOP-LABEL: splatconstant_funnnel_v16i8: ; XOP: # %bb.0: -; XOP-NEXT: vpshlb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 -; XOP-NEXT: vpshlb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; XOP-NEXT: vpor %xmm1, %xmm0, %xmm0 +; XOP-NEXT: vpsrlw $4, %xmm1, %xmm1 +; XOP-NEXT: vpsllw $4, %xmm0, %xmm0 +; XOP-NEXT: vpcmov {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0, %xmm0 ; XOP-NEXT: retq ; ; X86-SSE2-LABEL: splatconstant_funnnel_v16i8: diff --git a/llvm/test/CodeGen/X86/vector-fshr-256.ll b/llvm/test/CodeGen/X86/vector-fshr-256.ll index 3fabf720da71..7b6b0ea83c7e 100644 --- a/llvm/test/CodeGen/X86/vector-fshr-256.ll +++ b/llvm/test/CodeGen/X86/vector-fshr-256.ll @@ -2145,17 +2145,15 @@ define <32 x i8> @splatconstant_funnnel_v32i8(<32 x i8> %x, <32 x i8> %y) nounwi ; ; XOPAVX1-LABEL: splatconstant_funnnel_v32i8: ; XOPAVX1: # %bb.0: -; XOPAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 -; XOPAVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm2, %xmm2 -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm1, %xmm1 -; XOPAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 -; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 -; XOPAVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4] -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm2, %xmm2 -; XOPAVX1-NEXT: vpshlb %xmm3, %xmm0, %xmm0 -; XOPAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 -; XOPAVX1-NEXT: vorps %ymm1, %ymm0, %ymm0 +; XOPAVX1-NEXT: vpsrlw $4, %xmm1, %xmm2 +; XOPAVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; XOPAVX1-NEXT: vpsrlw $4, %xmm1, %xmm1 +; XOPAVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; XOPAVX1-NEXT: vpsllw $4, %xmm0, %xmm2 +; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; XOPAVX1-NEXT: vpsllw $4, %xmm0, %xmm0 +; XOPAVX1-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 +; XOPAVX1-NEXT: vpcmov {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0, %ymm0 ; XOPAVX1-NEXT: retq ; ; XOPAVX2-LABEL: splatconstant_funnnel_v32i8: -- GitLab From 5b4ed0dc9fac9144efe74da77517dcff46e731e9 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Fri, 19 Apr 2024 14:23:09 -0400 Subject: [PATCH 030/357] [test] Fix test. NFC - Add the missing token in @llvm.coro.end --- llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll b/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll index 24ad14be42be..4a2c10ca55cd 100644 --- a/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll +++ b/llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll @@ -79,7 +79,7 @@ resume: ret ptr %coro suspend: - call i1 @llvm.coro.end(ptr %coro, i1 0) + call i1 @llvm.coro.end(ptr %coro, i1 0, token none) ret ptr %coro } -- GitLab From 30b9537ff438366547f968c7909718e27d65c815 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 19 Apr 2024 11:52:02 -0700 Subject: [PATCH 031/357] [Driver] Add m_Group to -m[no-]strict-align so that `Args.ClaimAllArgs(options::OPT_CompileOnly_Group);` in Driver::handleArguments will claim the options even if only linking is performed. Fix #87945 --- clang/include/clang/Driver/Options.td | 4 ++-- clang/test/Driver/riscv-features.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d83031b05ceb..46225e2c7285 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4747,9 +4747,9 @@ def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group, HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group, HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; -def mstrict_align : Flag<["-"], "mstrict-align">, +def mstrict_align : Flag<["-"], "mstrict-align">, Group, HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">; -def mno_strict_align : Flag<["-"], "mno-strict-align">, +def mno_strict_align : Flag<["-"], "mno-strict-align">, Group, HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group, diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index 5e1db5ba1ed3..cfe293cd4667 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -37,6 +37,8 @@ // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mstrict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-UNALIGNED-ACCESS +// RUN: touch %t.o +// RUN: %clang --target=riscv32-unknown-elf -### %t.o -mno-strict-align -mstrict-align // FAST-UNALIGNED-ACCESS: "-target-feature" "+unaligned-scalar-mem" "-target-feature" "+unaligned-vector-mem" // NO-FAST-UNALIGNED-ACCESS: "-target-feature" "-unaligned-scalar-mem" "-target-feature" "-unaligned-vector-mem" -- GitLab From adc11b34b1d7f99b3931f945073a652f0dec5aaf Mon Sep 17 00:00:00 2001 From: Fabio D'Urso Date: Fri, 19 Apr 2024 21:27:53 +0200 Subject: [PATCH 032/357] Sync FuchsiaConfig with downstream's custom_scudo_config.h (#89244) Downstream disabled EnableContiguousRegions on RISCV-64 to avoid running out of virtual memory, but our tests still use the internal FuchsiaConfig class, which therefore needs to be changed too. --- compiler-rt/lib/scudo/standalone/allocator_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.h b/compiler-rt/lib/scudo/standalone/allocator_config.h index 1e0cf1015ba6..60f59bdd2f4c 100644 --- a/compiler-rt/lib/scudo/standalone/allocator_config.h +++ b/compiler-rt/lib/scudo/standalone/allocator_config.h @@ -146,6 +146,7 @@ struct FuchsiaConfig { // Support 39-bit VMA for riscv-64 static const uptr RegionSizeLog = 28U; static const uptr GroupSizeLog = 19U; + static const bool EnableContiguousRegions = false; #else static const uptr RegionSizeLog = 30U; static const uptr GroupSizeLog = 21U; -- GitLab From ce48f43f054f396fec50287cf8c7624bfaa5842a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 19 Apr 2024 12:38:53 -0700 Subject: [PATCH 033/357] [SelectionDAG] Require UADDO_CARRY carryin and carryout to have the same type. (#89255) This requires type legalization to keep them the same. This means we no longer need to legalize the operand since it will be legalized when we legalize the second result. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 4 ++-- .../SelectionDAG/LegalizeIntegerTypes.cpp | 20 +------------------ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 - .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 +- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a21b9acad7da..3cdb801bae7b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3359,7 +3359,7 @@ SDValue DAGCombiner::visitUADDO_CARRY(SDNode *N) { } /** - * If we are facing some sort of diamond carry propapagtion pattern try to + * If we are facing some sort of diamond carry propagation pattern try to * break it up to generate something like: * (uaddo_carry X, 0, (uaddo_carry A, B, Z):Carry) * @@ -3400,7 +3400,7 @@ static SDValue combineUADDO_CARRYDiamond(DAGCombiner &Combiner, Z = Carry0.getOperand(2); } else if (Carry0.getOpcode() == ISD::UADDO && isOneConstant(Carry0.getOperand(1))) { - EVT VT = Combiner.getSetCCResultType(Carry0.getValueType()); + EVT VT = Carry0->getValueType(1); Z = DAG.getConstant(1, SDLoc(Carry0.getOperand(1)), VT); } else { // We couldn't find a suitable Z. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 93ce9c22af55..55f9737bc94d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -949,7 +949,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_Overflow(SDNode *N) { unsigned NumOps = N->getNumOperands(); assert(NumOps <= 3 && "Too many operands"); if (NumOps == 3) - Ops[2] = N->getOperand(2); + Ops[2] = PromoteTargetBoolean(N->getOperand(2), VT); SDLoc dl(N); SDValue Res = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(VT, SVT), @@ -1867,11 +1867,6 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::FSHL: case ISD::FSHR: Res = PromoteIntOp_FunnelShift(N); break; - case ISD::SADDO_CARRY: - case ISD::SSUBO_CARRY: - case ISD::UADDO_CARRY: - case ISD::USUBO_CARRY: Res = PromoteIntOp_ADDSUBO_CARRY(N, OpNo); break; - case ISD::FRAMEADDR: case ISD::RETURNADDR: Res = PromoteIntOp_FRAMERETURNADDR(N); break; @@ -2373,19 +2368,6 @@ SDValue DAGTypeLegalizer::PromoteIntOp_VP_ZERO_EXTEND(SDNode *N) { N->getOperand(1), N->getOperand(2)); } -SDValue DAGTypeLegalizer::PromoteIntOp_ADDSUBO_CARRY(SDNode *N, unsigned OpNo) { - assert(OpNo == 2 && "Don't know how to promote this operand!"); - - SDValue LHS = N->getOperand(0); - SDValue RHS = N->getOperand(1); - SDValue Carry = N->getOperand(2); - SDLoc DL(N); - - Carry = PromoteTargetBoolean(Carry, LHS.getValueType()); - - return SDValue(DAG.UpdateNodeOperands(N, LHS, RHS, Carry), 0); -} - SDValue DAGTypeLegalizer::PromoteIntOp_FIX(SDNode *N) { SDValue Op2 = ZExtPromotedInteger(N->getOperand(2)); return SDValue( diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 919c0d4fd200..0483f7c74f91 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -389,7 +389,6 @@ private: SDValue PromoteIntOp_MLOAD(MaskedLoadSDNode *N, unsigned OpNo); SDValue PromoteIntOp_MSCATTER(MaskedScatterSDNode *N, unsigned OpNo); SDValue PromoteIntOp_MGATHER(MaskedGatherSDNode *N, unsigned OpNo); - SDValue PromoteIntOp_ADDSUBO_CARRY(SDNode *N, unsigned OpNo); SDValue PromoteIntOp_FRAMERETURNADDR(SDNode *N); SDValue PromoteIntOp_FIX(SDNode *N); SDValue PromoteIntOp_ExpOp(SDNode *N); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index f3441c9df0f8..7dbf83b7adee 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -9924,7 +9924,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, assert(VTList.VTs[0].isInteger() && VTList.VTs[1].isInteger() && Ops[0].getValueType() == Ops[1].getValueType() && Ops[0].getValueType() == VTList.VTs[0] && - Ops[2].getValueType().isInteger() && + Ops[2].getValueType() == VTList.VTs[1] && "Binary operator types must match!"); break; case ISD::SMUL_LOHI: -- GitLab From 016ce9ed5cd3694cbff72a768a593714913822ea Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 19 Apr 2024 12:39:32 -0700 Subject: [PATCH 034/357] [RISCV] Rename FeatureRVE to FeatureStdExtE. NFC (#89174) Planning to declare all extensions in tablegen so we can generate the tables for RISCVISAInfo.cpp. This requires making "e" consistent with other extensions. --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 2 +- .../Target/RISCV/Disassembler/RISCVDisassembler.cpp | 2 +- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp | 2 +- llvm/lib/Target/RISCV/RISCVFeatures.td | 8 ++++---- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 ++-- llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 12 ++++++------ 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 455a90269d02..d926ccdb59e1 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -83,7 +83,7 @@ class RISCVAsmParser : public MCTargetAsmParser { SMLoc getLoc() const { return getParser().getTok().getLoc(); } bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); } - bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureRVE); } + bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); } RISCVTargetStreamer &getTargetStreamer() { assert(getParser().getStreamer().getTargetStreamer() && diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index 6aadabdf1bc6..998b9181efe6 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -64,7 +64,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVDisassembler() { static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { - bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureRVE); + bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureStdExtE); if (RegNo >= 32 || (IsRVE && RegNo >= 16)) return MCDisassembler::Fail; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp index 5d9a58babe60..67c9060b5157 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -40,7 +40,7 @@ ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, StringRef ABIName) { auto TargetABI = getTargetABI(ABIName); bool IsRV64 = TT.isArch64Bit(); - bool IsRVE = FeatureBits[RISCV::FeatureRVE]; + bool IsRVE = FeatureBits[RISCV::FeatureStdExtE]; if (!ABIName.empty() && TargetABI == ABI_Unknown) { errs() diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 339c0397fa45..116e5a2ab734 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -16,6 +16,10 @@ def FeatureStdExtI : SubtargetFeature<"i", "HasStdExtI", "true", "'I' (Base Integer Instruction Set)">; +def FeatureStdExtE + : SubtargetFeature<"e", "HasStdExtE", "true", + "Implements RV{32,64}E (provides 16 rather than 32 GPRs)">; + def FeatureStdExtZic64b : SubtargetFeature<"zic64b", "HasStdExtZic64b", "true", "'Zic64b' (Cache Block Size Is 64 Bytes)">; @@ -1162,10 +1166,6 @@ def IsRV32 : Predicate<"!Subtarget->is64Bit()">, defvar RV32 = DefaultMode; def RV64 : HwMode<"+64bit", [IsRV64]>; -def FeatureRVE - : SubtargetFeature<"e", "IsRVE", "true", - "Implements RV{32,64}E (provides 16 rather than 32 GPRs)">; - def FeatureRelax : SubtargetFeature<"relax", "EnableLinkerRelax", "true", "Enable Linker relaxation.">; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index b0deb1d26699..82339dd20721 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -18951,7 +18951,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments( case CallingConv::RISCV_VectorCall: break; case CallingConv::GHC: - if (Subtarget.isRVE()) + if (Subtarget.hasStdExtE()) report_fatal_error("GHC calling convention is not supported on RVE!"); if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx()) report_fatal_error("GHC calling convention requires the (Zfinx/F) and " @@ -19189,7 +19189,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI, CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); if (CallConv == CallingConv::GHC) { - if (Subtarget.isRVE()) + if (Subtarget.hasStdExtE()) report_fatal_error("GHC calling convention is not supported on RVE!"); ArgCCInfo.AnalyzeCallOperands(Outs, RISCV::CC_RISCV_GHC); } else diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 367a62e830cb..6a48848e2022 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -65,10 +65,10 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { if (Subtarget.hasStdExtD()) return CSR_XLEN_F64_Interrupt_SaveList; if (Subtarget.hasStdExtF()) - return Subtarget.isRVE() ? CSR_XLEN_F32_Interrupt_RVE_SaveList - : CSR_XLEN_F32_Interrupt_SaveList; - return Subtarget.isRVE() ? CSR_Interrupt_RVE_SaveList - : CSR_Interrupt_SaveList; + return Subtarget.hasStdExtE() ? CSR_XLEN_F32_Interrupt_RVE_SaveList + : CSR_XLEN_F32_Interrupt_SaveList; + return Subtarget.hasStdExtE() ? CSR_Interrupt_RVE_SaveList + : CSR_Interrupt_SaveList; } bool HasVectorCSR = @@ -126,7 +126,7 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, RISCV::DUMMY_REG_PAIR_WITH_X0); // There are only 16 GPRs for RVE. - if (Subtarget.isRVE()) + if (Subtarget.hasStdExtE()) for (MCPhysReg Reg = RISCV::X16; Reg <= RISCV::X31; Reg++) markSuperRegs(Reserved, Reg); @@ -145,7 +145,7 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, RISCV::VCIX_STATE); if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { - if (Subtarget.isRVE()) + if (Subtarget.hasStdExtE()) report_fatal_error("Graal reserved registers do not exist in RVE"); markSuperRegs(Reserved, RISCV::X23); markSuperRegs(Reserved, RISCV::X27); -- GitLab From 8e2060bf210e83d6cc34f61185918ca67b54f6f1 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 19 Apr 2024 12:39:54 -0700 Subject: [PATCH 035/357] [X86][TableGen] Remove unnecessary use of formatted_raw_ostream. NFC (#89343) This code used to use the PadToColumn feature of formatted_raw_ostream, but no longer does. formatted_raw_ostream is slower than regular raw_ostream because it has to keep track of the number of character since the last new line character. --- llvm/utils/TableGen/X86FoldTablesEmitter.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp index 0e3674751fde..1440863ea561 100644 --- a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp @@ -15,7 +15,6 @@ #include "Common/CodeGenTarget.h" #include "X86RecognizableInstr.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/Support/X86FoldTablesUtils.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" @@ -95,7 +94,7 @@ class X86FoldTablesEmitter { const CodeGenInstruction *MemInst) : RegInst(RegInst), MemInst(MemInst) {} - void print(formatted_raw_ostream &OS) const { + void print(raw_ostream &OS) const { OS.indent(2); OS << "{X86::" << RegInst->TheDef->getName() << ", "; OS << "X86::" << MemInst->TheDef->getName() << ", "; @@ -222,7 +221,7 @@ private: // Print the given table as a static const C++ array of type // X86FoldTableEntry. void printTable(const FoldTable &Table, StringRef TableName, - formatted_raw_ostream &OS) { + raw_ostream &OS) { OS << "static const X86FoldTableEntry " << TableName << "[] = {\n"; for (auto &E : Table) @@ -619,9 +618,7 @@ void X86FoldTablesEmitter::updateTables(const CodeGenInstruction *RegInst, } } -void X86FoldTablesEmitter::run(raw_ostream &O) { - formatted_raw_ostream OS(O); - +void X86FoldTablesEmitter::run(raw_ostream &OS) { // Holds all memory instructions std::vector MemInsts; // Holds all register instructions - divided according to opcode. -- GitLab From 3ea5dff0efdbb4bf5590d882810aa42f9ec26e4e Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 19 Apr 2024 12:45:40 -0700 Subject: [PATCH 036/357] [clang][modules] Only avoid pruning module maps when asked to (#89428) Pruning non-affecting module maps is useful even when passing module maps explicitly via `-fmodule-map-file=`. For this situation, this patch reinstates the behavior we had prior to #87849. For the situation where the explicit module map file arguments were generated by the dependency scanner (which already pruned the non-affecting ones), this patch introduces new `-cc1` flag `-fno-modules-prune-non-affecting-module-map-files` that avoids the extra work. --- clang/include/clang/Driver/Options.td | 5 ++ clang/include/clang/Lex/HeaderSearchOptions.h | 7 ++- clang/lib/Serialization/ASTWriter.cpp | 6 +- .../DependencyScanning/ModuleDepCollector.cpp | 5 ++ clang/test/ClangScanDeps/modules-full.cpp | 3 + .../add-remove-irrelevant-module-map.m | 32 ---------- .../prune-non-affecting-module-map-files.m | 62 +++++++++++++++++++ 7 files changed, 84 insertions(+), 36 deletions(-) delete mode 100644 clang/test/Modules/add-remove-irrelevant-module-map.m create mode 100644 clang/test/Modules/prune-non-affecting-module-map-files.m diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 46225e2c7285..52d161703f96 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3100,6 +3100,11 @@ defm modules_skip_header_search_paths : BoolFOption<"modules-skip-header-search- HeaderSearchOpts<"ModulesSkipHeaderSearchPaths">, DefaultFalse, PosFlag, NegFlag, BothFlags<[], [CC1Option]>>; +def fno_modules_prune_non_affecting_module_map_files : + Flag<["-"], "fno-modules-prune-non-affecting-module-map-files">, + Group, Flags<[]>, Visibility<[CC1Option]>, + MarshallingInfoNegativeFlag>, + HelpText<"Do not prune non-affecting module map files when writing module files">; def fincremental_extensions : Flag<["-"], "fincremental-extensions">, diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h index 637dc77e5d95..e4437ac0e352 100644 --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -252,6 +252,10 @@ public: LLVM_PREFERRED_TYPE(bool) unsigned ModulesSkipPragmaDiagnosticMappings : 1; + /// Whether to prune non-affecting module map files from PCM files. + LLVM_PREFERRED_TYPE(bool) + unsigned ModulesPruneNonAffectingModuleMaps : 1; + LLVM_PREFERRED_TYPE(bool) unsigned ModulesHashContent : 1; @@ -280,7 +284,8 @@ public: ModulesValidateDiagnosticOptions(true), ModulesSkipDiagnosticOptions(false), ModulesSkipHeaderSearchPaths(false), - ModulesSkipPragmaDiagnosticMappings(false), ModulesHashContent(false), + ModulesSkipPragmaDiagnosticMappings(false), + ModulesPruneNonAffectingModuleMaps(true), ModulesHashContent(false), ModulesStrictContextHash(false), ModulesIncludeVFSUsage(false) {} /// AddPath - Add the \p Path path to the specified \p Group list. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6dd87b5d200d..8a4b36207c47 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -166,9 +166,9 @@ namespace { std::optional> GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) { - // Without implicit module map search, there's no good reason to know about - // any module maps that are not affecting. - if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ImplicitModuleMaps) + if (!PP.getHeaderSearchInfo() + .getHeaderSearchOpts() + .ModulesPruneNonAffectingModuleMaps) return std::nullopt; SmallVector ModulesToProcess{RootModule}; diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index e19f19b2528c..f46324ee9989 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -179,6 +179,11 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) { CI.resetNonModularOptions(); CI.clearImplicitModuleBuildOptions(); + // The scanner takes care to avoid passing non-affecting module maps to the + // explicit compiles. No need to do extra work just to find out there are no + // module map files to prune. + CI.getHeaderSearchOpts().ModulesPruneNonAffectingModuleMaps = false; + // Remove options incompatible with explicit module build or are likely to // differ between identical modules discovered from different translation // units. diff --git a/clang/test/ClangScanDeps/modules-full.cpp b/clang/test/ClangScanDeps/modules-full.cpp index 59efef0ecbaa..a00a431eb569 100644 --- a/clang/test/ClangScanDeps/modules-full.cpp +++ b/clang/test/ClangScanDeps/modules-full.cpp @@ -33,6 +33,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-emit-module" +// CHECK: "-fno-modules-prune-non-affecting-module-map-files" // CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H2_DINCLUDE]]/header2-{{[A-Z0-9]+}}.pcm" // CHECK-NOT: "-fimplicit-module-maps" // CHECK: "-fmodule-name=header1" @@ -51,6 +52,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1", // CHECK: "-emit-module", +// CHECK: "-fno-modules-prune-non-affecting-module-map-files" // CHECK-NOT: "-fimplicit-module-maps", // CHECK: "-fmodule-name=header1", // CHECK: "-fno-implicit-modules", @@ -68,6 +70,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1", // CHECK: "-emit-module", +// CHECK: "-fno-modules-prune-non-affecting-module-map-files" // CHECK: "-fmodule-name=header2", // CHECK-NOT: "-fimplicit-module-maps", // CHECK: "-fno-implicit-modules", diff --git a/clang/test/Modules/add-remove-irrelevant-module-map.m b/clang/test/Modules/add-remove-irrelevant-module-map.m deleted file mode 100644 index 7e3e58037e6f..000000000000 --- a/clang/test/Modules/add-remove-irrelevant-module-map.m +++ /dev/null @@ -1,32 +0,0 @@ -// RUN: rm -rf %t && mkdir %t -// RUN: split-file %s %t - -//--- a/module.modulemap -module a {} - -//--- b/module.modulemap -module b {} - -//--- c/module.modulemap -module c {} - -//--- module.modulemap -module m { header "m.h" } -//--- m.h -@import c; - -//--- test-simple.m -// expected-no-diagnostics -@import m; - -// Build modules with the non-affecting "a/module.modulemap". -// RUN: %clang_cc1 -I %t/a -I %t/b -I %t/c -I %t -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -fdisable-module-hash %t/test-simple.m -verify -// RUN: mv %t/cache %t/cache-with - -// Build modules without the non-affecting "a/module.modulemap". -// RUN: rm -rf %t/a/module.modulemap -// RUN: %clang_cc1 -I %t/a -I %t/b -I %t/c -I %t -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -fdisable-module-hash %t/test-simple.m -verify -// RUN: mv %t/cache %t/cache-without - -// Check that the PCM files are bit-for-bit identical. -// RUN: diff %t/cache-with/m.pcm %t/cache-without/m.pcm diff --git a/clang/test/Modules/prune-non-affecting-module-map-files.m b/clang/test/Modules/prune-non-affecting-module-map-files.m new file mode 100644 index 000000000000..ba2b3a306eaf --- /dev/null +++ b/clang/test/Modules/prune-non-affecting-module-map-files.m @@ -0,0 +1,62 @@ +// Check that the presence of non-affecting module map files does not affect the +// contents of PCM files. + +// RUN: rm -rf %t && mkdir %t +// RUN: split-file %s %t + +//--- a/module.modulemap +module a {} + +//--- b/module.modulemap +module b {} + +//--- c/module.modulemap +module c { header "c.h" } +//--- c/c.h +@import b; + +//--- tu.m +@import c; + +//--- explicit-mms-common-args.rsp +-fmodule-map-file=b/module.modulemap -fmodule-map-file=c/module.modulemap -fmodules -fmodules-cache-path=cache -fdisable-module-hash -fsyntax-only tu.m +//--- implicit-search-args.rsp +-I a -I b -I c -fimplicit-module-maps -fmodules -fmodules-cache-path=cache -fdisable-module-hash -fsyntax-only tu.m +//--- implicit-search-args.rsp-end + +// Test with explicit module map files. +// +// RUN: %clang_cc1 -working-directory %t @%t/explicit-mms-common-args.rsp +// RUN: mv %t/cache %t/cache-explicit-no-a-prune +// RUN: %clang_cc1 -working-directory %t @%t/explicit-mms-common-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-explicit-no-a-keep +// +// RUN: %clang_cc1 -working-directory %t -fmodule-map-file=a/module.modulemap @%t/explicit-mms-common-args.rsp +// RUN: mv %t/cache %t/cache-explicit-a-prune +// RUN: %clang_cc1 -working-directory %t -fmodule-map-file=a/module.modulemap @%t/explicit-mms-common-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-explicit-a-keep +// +// RUN: diff %t/cache-explicit-no-a-prune/c.pcm %t/cache-explicit-a-prune/c.pcm +// RUN: not diff %t/cache-explicit-no-a-keep/c.pcm %t/cache-explicit-a-keep/c.pcm + +// Test with implicit module map search. +// +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp +// RUN: mv %t/cache %t/cache-implicit-no-a-prune +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-implicit-no-a-keep +// +// FIXME: Instead of removing "a/module.modulemap" from the file system, we +// could drop the "-I a" search path argument in combination with the +// "-fmodules-skip-header-search-paths" flag. Unfortunately, that flag +// does not prevent serialization of the search path usage bit vector, +// making the files differ anyways. +// RUN: rm %t/a/module.modulemap +// +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp +// RUN: mv %t/cache %t/cache-implicit-a-prune +// RUN: %clang_cc1 -working-directory %t @%t/implicit-search-args.rsp -fno-modules-prune-non-affecting-module-map-files +// RUN: mv %t/cache %t/cache-implicit-a-keep +// +// RUN: diff %t/cache-implicit-no-a-prune/c.pcm %t/cache-implicit-a-prune/c.pcm +// RUN: not diff %t/cache-implicit-no-a-keep/c.pcm %t/cache-implicit-a-keep/c.pcm -- GitLab From aa7c104124ac4a8da12fbd25c797bc8ab438c545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 19 Apr 2024 12:47:40 -0700 Subject: [PATCH 037/357] [flang][cuda] Allow fixed size array with the managed attribute (#89436) Fixed size array and scalar should be allowed with the `managed` attribute. --- flang/lib/Semantics/check-declarations.cpp | 4 ++-- flang/test/Semantics/cuf03.cuf | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 875929e90fdd..adbd21dfe6d4 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -956,9 +956,9 @@ void CheckHelper::CheckObjectEntity( break; case common::CUDADataAttr::Managed: if (!IsAutomatic(symbol) && !IsAllocatable(symbol) && - !details.isDummy()) { + !details.isDummy() && !evaluate::IsExplicitShape(symbol)) { messages_.Say( - "Object '%s' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument"_err_en_US, + "Object '%s' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, explicit shape, or a dummy argument"_err_en_US, symbol.name()); } break; diff --git a/flang/test/Semantics/cuf03.cuf b/flang/test/Semantics/cuf03.cuf index 8decb8dcaa0f..020a1720aa2e 100644 --- a/flang/test/Semantics/cuf03.cuf +++ b/flang/test/Semantics/cuf03.cuf @@ -32,14 +32,11 @@ module m real, shared, target :: mst !ERROR: Object 'msa' with ATTRIBUTES(SHARED) must be declared in a device subprogram real, shared :: msa(*) - !ERROR: Object 'mm' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument - real, managed :: mm - !ERROR: Object 'mmi' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument - real, managed :: mmi = 1. + real, managed :: mm ! ok + real, managed :: mmi = 1. ! ok real, managed, allocatable :: mml ! ok - !ERROR: Object 'mmp' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument - real, managed, pointer :: mmp ! ok - !ERROR: Object 'mmt' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, or a dummy argument + !ERROR: Object 'mmp' with ATTRIBUTES(MANAGED) must also be allocatable, automatic, explicit shape, or a dummy argument + real, managed, pointer :: mmp(:) real, managed, target :: mmt !WARNING: Object 'mp' with ATTRIBUTES(PINNED) should also be allocatable real, pinned :: mp -- GitLab From c32712d1763d74329b42c1cd68a24d4c0075b596 Mon Sep 17 00:00:00 2001 From: Bill Wendling <5993918+bwendling@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:48:33 -0700 Subject: [PATCH 038/357] [Clang] Handle structs with inner structs and no fields (#89126) A struct that declares an inner struct, but no fields, won't have a field count. So getting the offset of the inner struct fails. This happens in both C and C++: struct foo { struct bar { int Quantizermatrix[]; }; }; Here 'struct foo' has no fields. Closes: https://github.com/llvm/llvm-project/issues/88931 --- clang/lib/CodeGen/CGBuiltin.cpp | 25 +++++++----- clang/test/CodeGen/attr-counted-by-pr88931.c | 40 +++++++++++++++++++ .../test/CodeGen/attr-counted-by-pr88931.cpp | 21 ++++++++++ 3 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 clang/test/CodeGen/attr-counted-by-pr88931.c create mode 100644 clang/test/CodeGen/attr-counted-by-pr88931.cpp diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a05874e63c73..4319501035e2 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -826,29 +826,32 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField( ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) { const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel(); - unsigned FieldNo = 0; - bool IsUnion = RD->isUnion(); + uint32_t FieldNo = 0; - for (const Decl *D : RD->decls()) { - if (const auto *Field = dyn_cast(D); - Field && (Name.empty() || Field->getNameAsString() == Name) && + if (RD->isImplicit()) + return nullptr; + + for (const FieldDecl *FD : RD->fields()) { + if ((Name.empty() || FD->getNameAsString() == Name) && Decl::isFlexibleArrayMemberLike( - Ctx, Field, Field->getType(), StrictFlexArraysLevel, + Ctx, FD, FD->getType(), StrictFlexArraysLevel, /*IgnoreTemplateOrMacroSubstitution=*/true)) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); Offset += Layout.getFieldOffset(FieldNo); - return Field; + return FD; } - if (const auto *Record = dyn_cast(D)) - if (const FieldDecl *Field = - FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) { + QualType Ty = FD->getType(); + if (Ty->isRecordType()) { + if (const FieldDecl *Field = FindFlexibleArrayMemberField( + Ctx, Ty->getAsRecordDecl(), Name, Offset)) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); Offset += Layout.getFieldOffset(FieldNo); return Field; } + } - if (!IsUnion && isa(D)) + if (!RD->isUnion()) ++FieldNo; } diff --git a/clang/test/CodeGen/attr-counted-by-pr88931.c b/clang/test/CodeGen/attr-counted-by-pr88931.c new file mode 100644 index 000000000000..cc3d751c7c6d --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-pr88931.c @@ -0,0 +1,40 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wno-missing-declarations -emit-llvm -o - %s | FileCheck %s + +struct foo { + int x,y,z; + struct bar { + int count; + int array[] __attribute__((counted_by(count))); + }; +}; + +void init(void * __attribute__((pass_dynamic_object_size(0)))); + +// CHECK-LABEL: define dso_local void @test1( +// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4 +// CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef -1) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: ret void +// +void test1(struct bar *p) { + init(p->array); +} + +struct mux { + int count; + int array[] __attribute__((counted_by(count))); +}; + +struct bux { struct mux x; }; + +// CHECK-LABEL: define dso_local void @test2( +// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @init(ptr noundef [[P]], i64 noundef -1) #[[ATTR2]] +// CHECK-NEXT: ret void +// +void test2(struct bux *p) { + init(p); +} diff --git a/clang/test/CodeGen/attr-counted-by-pr88931.cpp b/clang/test/CodeGen/attr-counted-by-pr88931.cpp new file mode 100644 index 000000000000..2a8cc1d07e50 --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-pr88931.cpp @@ -0,0 +1,21 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -emit-llvm -o - %s | FileCheck %s + +struct foo { + struct bar { + int array[]; + bar(); + }; +}; + +void init(void * __attribute__((pass_dynamic_object_size(0)))); + +// CHECK-LABEL: define dso_local void @_ZN3foo3barC1Ev( +// CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(1) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] align 2 { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @_Z4initPvU25pass_dynamic_object_size0(ptr noundef nonnull [[THIS]], i64 noundef -1) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: ret void +// +foo::bar::bar() { + init(array); +} -- GitLab From 0c455ee34823cb991a35e33ff020bb7cc4e44c8a Mon Sep 17 00:00:00 2001 From: Jan Leyonberg Date: Fri, 19 Apr 2024 15:50:55 -0400 Subject: [PATCH 039/357] [flang][OpenMP] Use maxnum/minnum for lowering of max/min reduction operators (#89258) This patch changes the lowering of max and min to be lowered to arith::MaxNumFop and arith::MinNumFOp instead of using arith::MaximumFOp and arith::MinimumFOp. The arith::MaximumFOp and arith::MinimumFOp map to the corresponding intrinsics llvm.maximum.* and llvm.minimum.* intrinsics which conform to the semantics specified in the draft of IEEE 754-2019, which is not supported by all hardware. Instead using arith::MaximumFOp and arith::MinimumFOp will allow code generation for more targets and match the code generated by clang OpenMP. fixes #87955 --- flang/lib/Lower/OpenMP/ReductionProcessor.cpp | 4 ++-- flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 | 2 +- flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 | 2 +- flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 | 2 +- flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 | 2 +- flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 | 2 +- flang/test/Lower/OpenMP/wsloop-reduction-max.f90 | 2 +- flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 | 2 +- flang/test/Lower/OpenMP/wsloop-reduction-min.f90 | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index 6a91ee4b32f6..9f8352a8025c 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -220,12 +220,12 @@ mlir::Value ReductionProcessor::createScalarCombiner( switch (redId) { case ReductionIdentifier::MAX: reductionOp = - getReductionOperation( + getReductionOperation( builder, type, loc, op1, op2); break; case ReductionIdentifier::MIN: reductionOp = - getReductionOperation( + getReductionOperation( builder, type, loc, op1, op2); break; case ReductionIdentifier::IOR: diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 index f0979ab95f56..80b720e3aac1 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 @@ -11,7 +11,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.maxnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 index 996296c2adc2..c3b821ea5912 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 @@ -6,7 +6,7 @@ !CHECK: omp.yield(%[[MINIMUM_VAL_F]] : f32) !CHECK: combiner !CHECK: ^bb0(%[[ARG0_F:.*]]: f32, %[[ARG1_F:.*]]: f32): -!CHECK: %[[COMB_VAL_F:.*]] = arith.maximumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 +!CHECK: %[[COMB_VAL_F:.*]] = arith.maxnumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 !CHECK: omp.yield(%[[COMB_VAL_F]] : f32) !CHECK: omp.declare_reduction @[[MAX_DECLARE_I:.*]] : i32 init { diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 index 24aa8e46e5bb..b284f8e5d967 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 @@ -11,7 +11,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.minnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 index 268f51c9dc93..ab33e180ed88 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 @@ -6,7 +6,7 @@ !CHECK: omp.yield(%[[MAXIMUM_VAL_F]] : f32) !CHECK: combiner !CHECK: ^bb0(%[[ARG0_F:.*]]: f32, %[[ARG1_F:.*]]: f32): -!CHECK: %[[COMB_VAL_F:.*]] = arith.minimumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 +!CHECK: %[[COMB_VAL_F:.*]] = arith.minnumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 !CHECK: omp.yield(%[[COMB_VAL_F]] : f32) !CHECK: omp.declare_reduction @[[MIN_DECLARE_I:.*]] : i32 init { diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 index ee562bbe1586..2f6921edcb42 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 @@ -13,7 +13,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.maxnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 index 6f11f0ec96a7..c9cf5cbf4f8c 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 @@ -10,7 +10,7 @@ ! CHECK-LABEL: } combiner { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32, %[[VAL_1:.*]]: f32): -! CHECK: %[[VAL_2:.*]] = arith.maximumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 +! CHECK: %[[VAL_2:.*]] = arith.maxnumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 index c0372117a03b..84a376b46b8f 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 @@ -13,7 +13,7 @@ !CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): !CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref !CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref -!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: %[[RES:.*]] = arith.minnumf %[[LD0]], %[[LD1]] {{.*}}: f32 !CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref !CHECK: omp.yield(%[[ARG0]] : !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 index 2c694f82e279..3ba279acd14c 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 @@ -10,7 +10,7 @@ ! CHECK-LABEL: } combiner { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32, %[[VAL_1:.*]]: f32): -! CHECK: %[[VAL_2:.*]] = arith.minimumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 +! CHECK: %[[VAL_2:.*]] = arith.minnumf %[[VAL_0]], %[[VAL_1]] fastmath : f32 ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } -- GitLab From cee7d994b94db625177cdfebcb8a6ce1ed677f85 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 19 Apr 2024 12:33:07 -0700 Subject: [PATCH 040/357] [SLP]Fix PR89438: Check for same vectorized node in MinBWs, not user. Need to check if the buildvector node has perfect diamond match in the graph and the matched node is resized. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 27 +++++- .../X86/gather-node-same-reduced.ll | 84 +++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 2e1788b83f11..1b56bb7b600c 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13139,9 +13139,30 @@ Value *BoUpSLP::vectorizeTree( assert(Vec->getType()->isIntOrIntVectorTy() && PrevVec->getType()->isIntOrIntVectorTy() && "Expected integer vector types only."); - assert(MinBWs.contains(TE->UserTreeIndices.front().UserTE) && - "Expected user in MinBWs."); - bool IsSigned = MinBWs.lookup(TE->UserTreeIndices.front().UserTE).second; + std::optional> Res; + if (const TreeEntry *BaseTE = getTreeEntry(TE->Scalars.front())) { + SmallVector BaseTEs; + if (BaseTE->isSame(TE->Scalars)) + BaseTEs.push_back(BaseTE); + auto It = MultiNodeScalars.find(TE->Scalars.front()); + if (It != MultiNodeScalars.end()) { + for (const TreeEntry *MNTE : It->getSecond()) + if (MNTE->isSame(TE->Scalars)) + BaseTEs.push_back(MNTE); + } + const auto *BaseIt = find_if(BaseTEs, [&](const TreeEntry *BaseTE) { + return MinBWs.contains(BaseTE); + }); + if (BaseIt != BaseTEs.end()) + Res = MinBWs.lookup(*BaseIt); + } + if (!Res) { + assert(MinBWs.contains(TE->UserTreeIndices.front().UserTE) && + "Expected user in MinBWs."); + Res = MinBWs.lookup(TE->UserTreeIndices.front().UserTE); + } + assert(Res && "Expected user node or perfect diamond match in MinBWs."); + bool IsSigned = Res->second; Vec = Builder.CreateIntCast(Vec, PrevVec->getType(), IsSigned); } PrevVec->replaceAllUsesWith(Vec); diff --git a/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll b/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll new file mode 100644 index 000000000000..b03eb9e67254 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll @@ -0,0 +1,84 @@ +; 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 < %s | FileCheck %s + +define i64 @test(ptr %p) { +; CHECK-LABEL: define i64 @test( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P]], i64 12 +; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i32> zeroinitializer, zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = xor <4 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i32> [[TMP3]], zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = xor <4 x i32> [[TMP4]], zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = xor <4 x i32> [[TMP5]], zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i32> [[TMP6]], zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i32> [[TMP7]], zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = xor <4 x i32> [[TMP8]], zeroinitializer +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i32> [[TMP9]], zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = xor <4 x i32> [[TMP10]], zeroinitializer +; CHECK-NEXT: [[TMP12:%.*]] = trunc <4 x i32> [[TMP11]] to <4 x i8> +; CHECK-NEXT: store <4 x i8> [[TMP12]], ptr [[TMP1]], align 1 +; CHECK-NEXT: ret i64 0 +; + %1 = getelementptr i8, ptr %p, i64 13 + %2 = getelementptr i8, ptr %p, i64 14 + %3 = getelementptr i8, ptr %p, i64 15 + %4 = getelementptr i8, ptr %p, i64 12 + %5 = zext i8 0 to i32 + %6 = and i32 %5, 0 + %.not866 = icmp eq i32 %6, 0 + %7 = select i1 %.not866, i32 0, i32 0 + %8 = xor i32 0, %7 + %9 = zext i8 0 to i32 + %10 = and i32 %9, 0 + %.not871 = icmp eq i32 %10, 0 + %11 = select i1 %.not871, i32 0, i32 0 + %12 = xor i32 0, %11 + %13 = xor i32 %9, 0 + %14 = xor i32 %13, 0 + %15 = xor i32 %14, 0 + %16 = xor i32 %15, 0 + %17 = xor i32 %16, 0 + %18 = xor i32 %17, %12 + %19 = xor i32 %18, 0 + %20 = xor i32 %19, 0 + %21 = xor i32 %20, 0 + %22 = xor i32 %21, 0 + %23 = trunc i32 %22 to i8 + store i8 %23, ptr %4, align 1 + %24 = xor i32 %9, 0 + %25 = xor i32 %24, 0 + %26 = xor i32 %25, 0 + %27 = xor i32 %26, 0 + %28 = xor i32 %27, 0 + %29 = xor i32 %28, %8 + %30 = xor i32 %29, 0 + %31 = xor i32 %30, 0 + %32 = xor i32 %31, 0 + %33 = xor i32 %32, 0 + %34 = trunc i32 %33 to i8 + store i8 %34, ptr %1, align 1 + %35 = xor i32 0, %5 + %36 = xor i32 %35, 0 + %37 = xor i32 %36, 0 + %38 = xor i32 %37, 0 + %39 = xor i32 %38, 0 + %40 = xor i32 %39, %8 + %41 = xor i32 %40, 0 + %42 = xor i32 %41, 0 + %43 = xor i32 %42, 0 + %44 = xor i32 %43, 0 + %45 = trunc i32 %44 to i8 + store i8 %45, ptr %2, align 1 + %46 = xor i32 %35, 0 + %47 = xor i32 %46, 0 + %48 = xor i32 %47, 0 + %49 = xor i32 %48, 0 + %50 = xor i32 %49, %8 + %51 = xor i32 %50, 0 + %52 = xor i32 %51, 0 + %53 = xor i32 %52, 0 + %54 = xor i32 %53, 0 + %55 = trunc i32 %54 to i8 + store i8 %55, ptr %3, align 1 + ret i64 0 +} -- GitLab From c8e65e193d542464421ad4f9a9965d45b302ac0c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 22:07:11 +0200 Subject: [PATCH 041/357] [clang] CTAD: Fix require-clause is not transformed. (#89378) Fixes https://github.com/llvm/llvm-project/issues/89013 When building the deduction guide, we use the TemplateArgsForBuildingFPrime to transform the require-clause from the underlying class deduction guide. However, we do this at the wrong place where not all elements of TemplateArgsForBuildingFPrime are initialized. The fix involves rearranging the transformRequireClause call to the correct location. As part of the fix, we extend the TemplateInstantiator to support more types in the template-rewrite mode. Otherwise, we will encounter an assertion error when attempting to rewrite the template type parameter type like D with a complex type like Derived. --- clang/lib/Sema/SemaTemplate.cpp | 27 ++++++++++--------- clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 +--- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 18 +++++++++++++ clang/test/SemaTemplate/deduction-guide.cpp | 28 ++++++++++++++++++++ 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d4976f9d0d11..4bda31ba67c0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2962,19 +2962,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getCanonicalTemplateArgument( Context.getInjectedTemplateArg(NewParam)); } - // Substitute new template parameters into requires-clause if present. - Expr *RequiresClause = - transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); - // FIXME: implement the is_deducible constraint per C++ - // [over.match.class.deduct]p3.3: - // ... and a constraint that is satisfied if and only if the arguments - // of A are deducible (see below) from the return type. - auto *FPrimeTemplateParamList = TemplateParameterList::Create( - Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), - AliasTemplate->getTemplateParameters()->getLAngleLoc(), - FPrimeTemplateParams, - AliasTemplate->getTemplateParameters()->getRAngleLoc(), - /*RequiresClause=*/RequiresClause); // To form a deduction guide f' from f, we leverage clang's instantiation // mechanism, we construct a template argument list where the template @@ -3020,6 +3007,20 @@ void DeclareImplicitDeductionGuidesForTypeAlias( F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), Sema::CodeSynthesisContext::BuildingDeductionGuides)) { auto *GG = cast(FPrime); + // Substitute new template parameters into requires-clause if present. + Expr *RequiresClause = + transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); + // FIXME: implement the is_deducible constraint per C++ + // [over.match.class.deduct]p3.3: + // ... and a constraint that is satisfied if and only if the arguments + // of A are deducible (see below) from the return type. + auto *FPrimeTemplateParamList = TemplateParameterList::Create( + Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), + AliasTemplate->getTemplateParameters()->getLAngleLoc(), + FPrimeTemplateParams, + AliasTemplate->getTemplateParameters()->getRAngleLoc(), + /*RequiresClause=*/RequiresClause); + buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList, GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), GG->getTypeSourceInfo(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3e6676f21c9b..98d5c7cb3a8a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2502,10 +2502,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, assert(Arg.getKind() == TemplateArgument::Type && "unexpected nontype template argument kind in template rewrite"); QualType NewT = Arg.getAsType(); - assert(isa(NewT) && - "type parm not rewritten to type parm"); - auto NewTL = TLB.push(NewT); - NewTL.setNameLoc(TL.getNameLoc()); + TLB.pushTrivial(SemaRef.Context, NewT, TL.getNameLoc()); return NewT; } diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 6f04264a655a..508a3a5da76a 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -289,3 +289,21 @@ using String = Array; // Verify no crash on constructing the aggregate deduction guides. String s("hello"); } // namespace test21 + +// GH89013 +namespace test22 { +class Base {}; +template +class Derived final : public Base {}; + +template +requires __is_base_of(Base, D) +struct Foo { + explicit Foo(D) {} +}; + +template +using AFoo = Foo>; + +AFoo a(Derived{}); +} // namespace test22 diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 58f08aa1eed6..29cc5a9b996f 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -260,3 +260,31 @@ AG ag = {1}; // CHECK: |-TemplateArgument type 'int' // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' + +template +requires (sizeof(D) == 4) +struct Foo { + Foo(D); +}; + +template +using AFoo = Foo>; +// Verify that the require-clause from the Foo deduction guide is transformed. +// The D occurrence should be rewritten to G. +// +// CHECK-LABEL: Dumping +// CHECK: FunctionTemplateDecl {{.*}} implicit +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 U +// CHECK-NEXT: |-ParenExpr {{.*}} 'bool' +// CHECK-NEXT: | `-BinaryOperator {{.*}} 'bool' '==' +// CHECK-NEXT: | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'G' +// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'unsigned long' +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (G) -> Foo>' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} 'G' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (G) -> Foo>' implicit_instantiation +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +// CHECK-NEXT: `-ParmVarDecl {{.*}} 'G' + +AFoo aa(G{}); -- GitLab From 08163cd9d82690e808c28515523b5fd0923d7b38 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 19 Apr 2024 22:14:55 +0200 Subject: [PATCH 042/357] [lldb] Provide a better error message for missing symbols (#89433) This adds a hint to the missing symbols error message to make it easier to understand what this means to users. --- lldb/source/Expression/IRExecutionUnit.cpp | 4 +++- lldb/test/API/lang/cpp/constructors/TestCppConstructors.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index cb9bee8733e1..07df8c52a2a4 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -431,7 +431,9 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, } m_failed_lookups.clear(); - + ss.PutCString( + "\nHint: The expression tried to call a function that is not present " + "in the target, perhaps because it was optimized out by the compiler."); error.SetErrorString(ss.GetString()); return; diff --git a/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py b/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py index 6724bfc8ed78..140877adba73 100644 --- a/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py +++ b/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py @@ -47,7 +47,7 @@ class TestCase(TestBase): self.expect( "expr ClassWithDeletedDefaultCtor().value", error=True, - substrs=["Couldn't look up symbols:"], + substrs=["Couldn't look up symbols:", "function missing"], ) @skipIfWindows # Can't find operator new. -- GitLab From d634b233640dc38cf5f673a9cfcd1fe55124430a Mon Sep 17 00:00:00 2001 From: Samira Bazuzi Date: Fri, 19 Apr 2024 16:23:43 -0400 Subject: [PATCH 043/357] [clang][dataflow] Expose getReferencedDecls for a Stmt. (#89444) --- clang/include/clang/Analysis/FlowSensitive/ASTOps.h | 3 +++ clang/lib/Analysis/FlowSensitive/ASTOps.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index f9fd3db1fb67..05748f300a93 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -96,6 +96,9 @@ struct ReferencedDecls { /// Returns declarations that are declared in or referenced from `FD`. ReferencedDecls getReferencedDecls(const FunctionDecl &FD); +/// Returns declarations that are declared in or referenced from `S`. +ReferencedDecls getReferencedDecls(const Stmt &S); + } // namespace dataflow } // namespace clang diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp index 6f179c1403b6..619bf772bba5 100644 --- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp @@ -261,4 +261,10 @@ ReferencedDecls getReferencedDecls(const FunctionDecl &FD) { return Result; } +ReferencedDecls getReferencedDecls(const Stmt &S) { + ReferencedDecls Result; + getReferencedDecls(S, Result); + return Result; +} + } // namespace clang::dataflow -- GitLab From 5232cec8f947ed8bff4ca57f990954228d58e66d Mon Sep 17 00:00:00 2001 From: Nicolas van Kempen Date: Fri, 19 Apr 2024 17:00:13 -0400 Subject: [PATCH 044/357] Apply modernize-use-starts-ends-with on llvm-project (#89140) Run `modernize-use-starts-ends-with` on llvm-project. Two instances are flagged, minor readability improvements, extremely minor performance improvements. ``` python3 clang-tools-extra/clang-tidy/tool/run-clang-tidy.py \ -clang-tidy-binary="build/bin/clang-tidy" \ -clang-apply-replacements-binary="build/bin/clang-apply-replacements" \ -checks="-*,modernize-use-starts-ends-with" \ -header-filter=".*" \ -fix -format ``` I am working on some additions to this check, but they don't seem to flag any additional cases anyway. --- clang-tools-extra/clang-doc/Representation.cpp | 4 ++-- lldb/unittests/Host/FileSystemTest.cpp | 2 +- llvm/unittests/Support/VirtualFileSystemTest.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 84233c36e15d..2afff2929cf7 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -380,8 +380,8 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx, this->SourceRoot = std::string(SourceRootDir); if (!RepositoryUrl.empty()) { this->RepositoryUrl = std::string(RepositoryUrl); - if (!RepositoryUrl.empty() && RepositoryUrl.find("http://") != 0 && - RepositoryUrl.find("https://") != 0) + if (!RepositoryUrl.empty() && !RepositoryUrl.starts_with("http://") && + !RepositoryUrl.starts_with("https://")) this->RepositoryUrl->insert(0, "https://"); } } diff --git a/lldb/unittests/Host/FileSystemTest.cpp b/lldb/unittests/Host/FileSystemTest.cpp index 3b5ee7c8bc22..58887f6b2467 100644 --- a/lldb/unittests/Host/FileSystemTest.cpp +++ b/lldb/unittests/Host/FileSystemTest.cpp @@ -93,7 +93,7 @@ public: std::map::iterator I; std::string Path; bool isInPath(StringRef S) { - if (Path.size() < S.size() && S.find(Path) == 0) { + if (Path.size() < S.size() && S.starts_with(Path)) { auto LastSep = S.find_last_of('/'); if (LastSep == Path.size() || LastSep == Path.size() - 1) return true; diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp index e9b4ac3d92e1..e9fd9671ea6a 100644 --- a/llvm/unittests/Support/VirtualFileSystemTest.cpp +++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp @@ -101,7 +101,7 @@ public: std::map::iterator I; std::string Path; bool isInPath(StringRef S) { - if (Path.size() < S.size() && S.find(Path) == 0) { + if (Path.size() < S.size() && S.starts_with(Path)) { auto LastSep = S.find_last_of('/'); if (LastSep == Path.size() || LastSep == Path.size() - 1) return true; -- GitLab From 45432eec0ae6a7f7452196eb099814d1a7dc2c0f Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 19 Apr 2024 14:21:03 -0700 Subject: [PATCH 045/357] [ARM64EC] Add softintrin.lib as an implicit dependency to object files. (#89171) This copies MSVC behavior, and avoids weird link errors in certain cases. --- clang/lib/Driver/ToolChains/Clang.cpp | 12 +++++++++--- clang/test/Driver/cl-options.c | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 456ea74caadb..97b4aa1c9b1d 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4733,7 +4733,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, Output.getFilename()); } -static void ProcessVSRuntimeLibrary(const ArgList &Args, +static void ProcessVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { unsigned RTOptionID = options::OPT__SLASH_MT; @@ -4796,6 +4796,12 @@ static void ProcessVSRuntimeLibrary(const ArgList &Args, // implemented in clang. CmdArgs.push_back("--dependent-lib=oldnames"); } + + // All Arm64EC object files implicitly add softintrin.lib. This is necessary + // even if the file doesn't actually refer to any of the routines because + // the CRT itself has incomplete dependency markings. + if (TC.getTriple().isWindowsArm64EC()) + CmdArgs.push_back("--dependent-lib=softintrin"); } void Clang::ConstructJob(Compilation &C, const JobAction &JA, @@ -7051,7 +7057,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() && Args.hasArg(options::OPT_fms_runtime_lib_EQ)) - ProcessVSRuntimeLibrary(Args, CmdArgs); + ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs); // Handle -fgcc-version, if present. VersionTuple GNUCVer; @@ -8178,7 +8184,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, ArgStringList &CmdArgs) const { bool isNVPTX = getToolChain().getTriple().isNVPTX(); - ProcessVSRuntimeLibrary(Args, CmdArgs); + ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs); if (Arg *ShowIncludes = Args.getLastArg(options::OPT__SLASH_showIncludes, diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 5b6dfe308a76..7731300ae9f5 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -790,6 +790,7 @@ // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC %s // ARM64EC-NOT: /arm64EC has been overridden by specified target // ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.33.0" +// ARM64EC-SAME: "--dependent-lib=softintrin" // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s // ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored -- GitLab From 5bcf31ebfad8b32aed20dd47be6238cc19710e63 Mon Sep 17 00:00:00 2001 From: Bill Wendling <5993918+bwendling@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:38:17 -0700 Subject: [PATCH 046/357] [Clang] Loop over FieldDecls instead of all Decls (#89453) Only FieldDecls are of importance here. A struct defined within another struct has the same semantics as if it were defined outside of the struct. So there's no need to look into RecordDecls that aren't a field. --- clang/lib/CodeGen/CGBuiltin.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4319501035e2..4ab844d206e4 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -861,14 +861,13 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField( static unsigned CountCountedByAttrs(const RecordDecl *RD) { unsigned Num = 0; - for (const Decl *D : RD->decls()) { - if (const auto *FD = dyn_cast(D); - FD && FD->getType()->isCountAttributedType()) { + for (const FieldDecl *FD : RD->fields()) { + if (FD->getType()->isCountAttributedType()) return ++Num; - } - if (const auto *Rec = dyn_cast(D)) - Num += CountCountedByAttrs(Rec); + QualType Ty = FD->getType(); + if (Ty->isRecordType()) + Num += CountCountedByAttrs(Ty->getAsRecordDecl()); } return Num; -- GitLab From 2a632d3d9f5c70db38c617b0816deb37ef722a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 19 Apr 2024 14:49:56 -0700 Subject: [PATCH 047/357] [flang][cuda] Use fir.cuda_deallocate for automatic deallocation (#89450) Automatic deallocation of allocatable that are cuda device variable must use the fir.cuda_deallocate operation. This patch update the automatic deallocation code generation to use this operation when the variable is a cuda variable. --- flang/include/flang/Lower/Allocatable.h | 4 ++- flang/lib/Lower/Allocatable.cpp | 12 +++++---- flang/lib/Lower/ConvertVariable.cpp | 5 ++-- flang/test/Lower/CUDA/cuda-allocatable.cuf | 30 ++++++++++++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/flang/include/flang/Lower/Allocatable.h b/flang/include/flang/Lower/Allocatable.h index d3c16de377c1..e8738f0407e7 100644 --- a/flang/include/flang/Lower/Allocatable.h +++ b/flang/include/flang/Lower/Allocatable.h @@ -55,12 +55,14 @@ void genDeallocateStmt(AbstractConverter &converter, void genDeallocateBox(AbstractConverter &converter, const fir::MutableBoxValue &box, mlir::Location loc, + const Fortran::semantics::Symbol *sym = nullptr, mlir::Value declaredTypeDesc = {}); /// Deallocate an allocatable if it is allocated at the end of its lifetime. void genDeallocateIfAllocated(AbstractConverter &converter, const fir::MutableBoxValue &box, - mlir::Location loc); + mlir::Location loc, + const Fortran::semantics::Symbol *sym = nullptr); /// Create a MutableBoxValue for an allocatable or pointer entity. /// If the variables is a local variable that is not a dummy, it will be diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 38f61528d7e2..8e84ea2fc5d5 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -859,18 +859,20 @@ genDeallocate(fir::FirOpBuilder &builder, void Fortran::lower::genDeallocateBox( Fortran::lower::AbstractConverter &converter, const fir::MutableBoxValue &box, mlir::Location loc, - mlir::Value declaredTypeDesc) { + const Fortran::semantics::Symbol *sym, mlir::Value declaredTypeDesc) { const Fortran::lower::SomeExpr *statExpr = nullptr; const Fortran::lower::SomeExpr *errMsgExpr = nullptr; ErrorManager errorManager; errorManager.init(converter, loc, statExpr, errMsgExpr); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - genDeallocate(builder, converter, loc, box, errorManager, declaredTypeDesc); + genDeallocate(builder, converter, loc, box, errorManager, declaredTypeDesc, + sym); } void Fortran::lower::genDeallocateIfAllocated( Fortran::lower::AbstractConverter &converter, - const fir::MutableBoxValue &box, mlir::Location loc) { + const fir::MutableBoxValue &box, mlir::Location loc, + const Fortran::semantics::Symbol *sym) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Value isAllocated = fir::factory::genIsAllocatedOrAssociatedTest(builder, loc, box); @@ -880,9 +882,9 @@ void Fortran::lower::genDeallocateIfAllocated( eleType.isa() && box.isPolymorphic()) { mlir::Value declaredTypeDesc = builder.create( loc, mlir::TypeAttr::get(eleType)); - genDeallocateBox(converter, box, loc, declaredTypeDesc); + genDeallocateBox(converter, box, loc, sym, declaredTypeDesc); } else { - genDeallocateBox(converter, box, loc); + genDeallocateBox(converter, box, loc, sym); } }) .end(); diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 2d2d9eba905b..c40435c0977c 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -916,13 +916,14 @@ static void instantiateLocal(Fortran::lower::AbstractConverter &converter, break; case VariableCleanUp::Deallocate: auto *converterPtr = &converter; - converter.getFctCtx().attachCleanup([converterPtr, loc, exv]() { + auto *sym = &var.getSymbol(); + converter.getFctCtx().attachCleanup([converterPtr, loc, exv, sym]() { const fir::MutableBoxValue *mutableBox = exv.getBoxOf(); assert(mutableBox && "trying to deallocate entity not lowered as allocatable"); Fortran::lower::genDeallocateIfAllocated(*converterPtr, *mutableBox, - loc); + loc, sym); }); } } diff --git a/flang/test/Lower/CUDA/cuda-allocatable.cuf b/flang/test/Lower/CUDA/cuda-allocatable.cuf index 5b10334ecdbc..adbf1722731a 100644 --- a/flang/test/Lower/CUDA/cuda-allocatable.cuf +++ b/flang/test/Lower/CUDA/cuda-allocatable.cuf @@ -17,6 +17,15 @@ end subroutine ! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: %[[BOX_LOAD:.*]] = fir.load %[[BOX_DECL]]#1 : !fir.ref>>> +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX_LOAD]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[ADDR_I64:.*]] = fir.convert %[[ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[NE_C0:.*]] = arith.cmpi ne, %[[ADDR_I64]], %[[C0]] : i64 +! CHECK: fir.if %[[NE_C0]] { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } + subroutine sub2() real, allocatable, managed :: a(:) integer :: istat @@ -37,6 +46,10 @@ end subroutine ! CHECK: %[[STAT:.*]] = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda, hasStat} -> i32 ! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref +! CHECK: fir.if %{{.*}} { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } + subroutine sub3() integer, allocatable, pinned :: a(:,:) logical :: plog @@ -50,6 +63,9 @@ end subroutine ! CHECK: %[[PLOG_DECL:.*]]:2 = hlfir.declare %5 {uniq_name = "_QFsub3Eplog"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK-2: fir.call @_FortranAAllocatableSetBounds ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> pinned(%[[PLOG_DECL]]#1 : !fir.ref>) {cuda_attr = #fir.cuda} -> i32 +! CHECK: fir.if %{{.*}} { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } subroutine sub4() real, allocatable, unified :: a(:) @@ -65,6 +81,9 @@ end subroutine ! CHECK: fir.call @_FortranAAllocatableSetBounds ! CHECK: %[[STREAM:.*]] = fir.load %[[ISTREAM_DECL]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> stream(%[[STREAM]] : i32) {cuda_attr = #fir.cuda} -> i32 +! CHECK: fir.if %{{.*}} { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } subroutine sub5() real, allocatable, device :: a(:) @@ -80,6 +99,11 @@ end subroutine ! CHECK: %[[LOAD_B:.*]] = fir.load %[[BOX_B_DECL]]#1 : !fir.ref>>> ! CHECK: fir.call @_FortranAAllocatableSetBounds ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_A_DECL]]#1 : !fir.ref>>> source(%[[LOAD_B]] : !fir.box>>) {cuda_attr = #fir.cuda} -> i32 +! CHECK: fir.if +! CHECK: fir.freemem +! CHECK: fir.if %{{.*}} { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } subroutine sub6() real, allocatable, device :: a(:) @@ -95,6 +119,9 @@ end subroutine ! CHECK: %[[LOAD_B:.*]] = fir.load %[[BOX_B_DECL]]#1 : !fir.ref>>> ! CHECK: fir.call @_FortranAAllocatableApplyMold ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: fir.if %{{.*}} { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } subroutine sub7() real, allocatable, device :: a(:) @@ -120,3 +147,6 @@ end subroutine ! CHECK: %[[ERR_BOX:.*]] = fir.embox %[[ERR_DECL]]#1 : (!fir.ref>) -> !fir.box> ! CHECK: %[[STAT:.*]] = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> errmsg(%15 : !fir.box>) {cuda_attr = #fir.cuda, hasStat} -> i32 ! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref +! CHECK: fir.if %{{.*}} { +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: } -- GitLab From 7c3dfb29dc4b5345da6a7fb25f92bf8d2919bce9 Mon Sep 17 00:00:00 2001 From: Maksim Levental Date: Fri, 19 Apr 2024 16:52:04 -0500 Subject: [PATCH 048/357] [mlir][python] fix memref._is_constant_int_like (#89447) --- mlir/python/mlir/dialects/memref.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlir/python/mlir/dialects/memref.py b/mlir/python/mlir/dialects/memref.py index a3d783415855..bc9a3a52728a 100644 --- a/mlir/python/mlir/dialects/memref.py +++ b/mlir/python/mlir/dialects/memref.py @@ -8,12 +8,13 @@ from typing import Optional from ._memref_ops_gen import * from ._ods_common import _dispatch_mixed_values, MixedValues from .arith import ConstantOp, _is_integer_like_type -from ..ir import Value, MemRefType, StridedLayoutAttr, ShapedType +from ..ir import Value, MemRefType, StridedLayoutAttr, ShapedType, Operation def _is_constant_int_like(i): return ( isinstance(i, Value) + and isinstance(i.owner, Operation) and isinstance(i.owner.opview, ConstantOp) and _is_integer_like_type(i.type) ) -- GitLab From 16e3464852efe3001060ff7feb3261dd397bfe84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 19 Apr 2024 14:58:22 -0700 Subject: [PATCH 049/357] [flang][cuda] Enforce PINNED attribute when ALLOCATE with PINNED option (#89455) When the PINNED option is specified on an ALLOCATE statement, the object must have the PINNED attribute. --- flang/lib/Semantics/check-allocate.cpp | 7 +++++++ flang/test/Semantics/cuf07.cuf | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp index a7244e1c5833..7bfd86262b3d 100644 --- a/flang/lib/Semantics/check-allocate.cpp +++ b/flang/lib/Semantics/check-allocate.cpp @@ -611,6 +611,13 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) { return false; } } + if (allocateInfo_.gotPinned) { + std::optional cudaAttr{GetCUDADataAttr(ultimate_)}; + if (!cudaAttr || *cudaAttr != common::CUDADataAttr::Pinned) { + context.Say(name_.source, + "Object in ALLOCATE must have PINNED attribute when PINNED option is specified"_err_en_US); + } + } return RunCoarrayRelatedChecks(context); } diff --git a/flang/test/Semantics/cuf07.cuf b/flang/test/Semantics/cuf07.cuf index b520b5da5126..91a78e124c59 100644 --- a/flang/test/Semantics/cuf07.cuf +++ b/flang/test/Semantics/cuf07.cuf @@ -23,4 +23,12 @@ module m !BECAUSE: 'ma' is a host-associated allocatable and is not definable in a device subprogram deallocate(ma) end subroutine + + subroutine hostsub() + integer, allocatable, device :: ia(:) + logical :: plog + + !ERROR: Object in ALLOCATE must have PINNED attribute when PINNED option is specified + allocate(ia(100), pinned = plog) + end subroutine end module -- GitLab From 4523a267829c807f3fc8fab8e5e9613985a51565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 19 Apr 2024 15:19:37 -0700 Subject: [PATCH 050/357] [flang][cuda] Enforce DEVICE attribute when ALLOCATE with STREAM option (#89459) When the STREAM option is specified on an ALLOCATE statement, the object must have the DEVICE attribute. --- flang/lib/Semantics/check-allocate.cpp | 7 +++++++ flang/test/Lower/CUDA/cuda-allocatable.cuf | 8 ++++---- flang/test/Parser/cuf-sanity-common | 2 +- flang/test/Parser/cuf-sanity-tree.CUF | 2 -- flang/test/Parser/cuf-sanity-unparse.CUF | 2 +- flang/test/Semantics/cuf07.cuf | 8 ++++++++ 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp index 7bfd86262b3d..b4c566067057 100644 --- a/flang/lib/Semantics/check-allocate.cpp +++ b/flang/lib/Semantics/check-allocate.cpp @@ -618,6 +618,13 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) { "Object in ALLOCATE must have PINNED attribute when PINNED option is specified"_err_en_US); } } + if (allocateInfo_.gotStream) { + std::optional cudaAttr{GetCUDADataAttr(ultimate_)}; + if (!cudaAttr || *cudaAttr != common::CUDADataAttr::Device) { + context.Say(name_.source, + "Object in ALLOCATE must have DEVICE attribute when STREAM option is specified"_err_en_US); + } + } return RunCoarrayRelatedChecks(context); } diff --git a/flang/test/Lower/CUDA/cuda-allocatable.cuf b/flang/test/Lower/CUDA/cuda-allocatable.cuf index adbf1722731a..eff5f13669e9 100644 --- a/flang/test/Lower/CUDA/cuda-allocatable.cuf +++ b/flang/test/Lower/CUDA/cuda-allocatable.cuf @@ -68,21 +68,21 @@ end subroutine ! CHECK: } subroutine sub4() - real, allocatable, unified :: a(:) + real, allocatable, device :: a(:) integer :: istream allocate(a(10), stream=istream) end subroutine ! CHECK-LABEL: func.func @_QPsub4() ! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFsub4Ea"} -! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %0 {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub4Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[BOX_DECL:.*]]:2 = hlfir.declare %0 {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub4Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) ! CHECK: %[[ISTREAM:.*]] = fir.alloca i32 {bindc_name = "istream", uniq_name = "_QFsub4Eistream"} ! CHECK: %[[ISTREAM_DECL:.*]]:2 = hlfir.declare %[[ISTREAM]] {uniq_name = "_QFsub4Eistream"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.call @_FortranAAllocatableSetBounds ! CHECK: %[[STREAM:.*]] = fir.load %[[ISTREAM_DECL]]#0 : !fir.ref -! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> stream(%[[STREAM]] : i32) {cuda_attr = #fir.cuda} -> i32 +! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> stream(%[[STREAM]] : i32) {cuda_attr = #fir.cuda} -> i32 ! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 +! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 ! CHECK: } subroutine sub5() diff --git a/flang/test/Parser/cuf-sanity-common b/flang/test/Parser/cuf-sanity-common index 7f4217fb5835..b097a6aa3004 100644 --- a/flang/test/Parser/cuf-sanity-common +++ b/flang/test/Parser/cuf-sanity-common @@ -32,6 +32,6 @@ module m call globalsub<<<1, 2>>> call globalsub<<<1, 2, 3>>> call globalsub<<<1, 2, 3, 4>>> - allocate(pa(32), stream = 1, pinned = isPinned) + allocate(pa(32), pinned = isPinned) end subroutine end module diff --git a/flang/test/Parser/cuf-sanity-tree.CUF b/flang/test/Parser/cuf-sanity-tree.CUF index dc12759d3ce5..2820441d5b5f 100644 --- a/flang/test/Parser/cuf-sanity-tree.CUF +++ b/flang/test/Parser/cuf-sanity-tree.CUF @@ -199,8 +199,6 @@ include "cuf-sanity-common" !CHECK: | | | | | | AllocateShapeSpec !CHECK: | | | | | | | Scalar -> Integer -> Expr = '32_4' !CHECK: | | | | | | | | LiteralConstant -> IntLiteralConstant = '32' -!CHECK: | | | | | AllocOpt -> Stream -> Scalar -> Integer -> Expr = '1_4' -!CHECK: | | | | | | LiteralConstant -> IntLiteralConstant = '1' !CHECK: | | | | | AllocOpt -> Pinned -> Scalar -> Logical -> Variable = 'ispinned' !CHECK: | | | | | | Designator -> DataRef -> Name = 'ispinned' !CHECK: | | | EndSubroutineStmt -> diff --git a/flang/test/Parser/cuf-sanity-unparse.CUF b/flang/test/Parser/cuf-sanity-unparse.CUF index 7ac39448d7bd..b6921e74fc05 100644 --- a/flang/test/Parser/cuf-sanity-unparse.CUF +++ b/flang/test/Parser/cuf-sanity-unparse.CUF @@ -37,6 +37,6 @@ include "cuf-sanity-common" !CHECK: CALL globalsub<<<1_4,2_4>>>() !CHECK: CALL globalsub<<<1_4,2_4,3_4>>>() !CHECK: CALL globalsub<<<1_4,2_4,3_4,4_4>>>() -!CHECK: ALLOCATE(pa(32_4), STREAM=1_4, PINNED=ispinned) +!CHECK: ALLOCATE(pa(32_4), PINNED=ispinned) !CHECK: END SUBROUTINE !CHECK: END MODULE diff --git a/flang/test/Semantics/cuf07.cuf b/flang/test/Semantics/cuf07.cuf index 91a78e124c59..c48abb5adf0d 100644 --- a/flang/test/Semantics/cuf07.cuf +++ b/flang/test/Semantics/cuf07.cuf @@ -31,4 +31,12 @@ module m !ERROR: Object in ALLOCATE must have PINNED attribute when PINNED option is specified allocate(ia(100), pinned = plog) end subroutine + + subroutine host2() + integer, allocatable, pinned :: ia(:) + integer :: istream + + !ERROR: Object in ALLOCATE must have DEVICE attribute when STREAM option is specified + allocate(ia(100), stream = istream) + end subroutine end module -- GitLab From d9169ffaf7c01691644537d3443240748b107359 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 19 Apr 2024 15:29:14 -0700 Subject: [PATCH 051/357] [BOLT,test] Update AArch64/constant_island_pie_update.s after llvm-readelf -r RELR change --- bolt/test/AArch64/constant_island_pie_update.s | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bolt/test/AArch64/constant_island_pie_update.s b/bolt/test/AArch64/constant_island_pie_update.s index 0ab67d07a854..313e103b19c0 100644 --- a/bolt/test/AArch64/constant_island_pie_update.s +++ b/bolt/test/AArch64/constant_island_pie_update.s @@ -18,7 +18,7 @@ # RUN: llvm-objdump -j .text -d --show-all-symbols %t.relr.bolt | FileCheck %s # RUN: llvm-objdump -j .text -d %t.relr.bolt | \ # RUN: FileCheck %s --check-prefix=ADDENDCHECK -# RUN: llvm-readelf -rsW %t.relr.bolt | FileCheck --check-prefix=ELFCHECK %s +# RUN: llvm-readelf -rsW %t.relr.bolt | FileCheck --check-prefix=RELRELFCHECK %s # RUN: llvm-readelf -SW %t.relr.bolt | FileCheck --check-prefix=RELRSZCHECK %s // Check that the CI value was updated @@ -51,6 +51,12 @@ # ELFCHECK-NEXT: {{.*}} R_AARCH64_RELATIVE # ELFCHECK: {{.*}}[[#OFF]] {{.*}} $d +# RELRELFCHECK: $d{{$}} +# RELRELFCHECK-NEXT: $d + 0x8{{$}} +# RELRELFCHECK-NEXT: $d + 0x18{{$}} +# RELRELFCHECK-NEXT: mytextP +# RELRELFCHECK-EMPTY: + // Check that .relr.dyn size is 2 bytes to ensure that last 3 relocations were // encoded as a bitmap so the total section size for 3 relocations is 2 bytes. # RELRSZCHECK: .relr.dyn RELR [[#%x,ADDR:]] [[#%x,OFF:]] {{0*}}10 -- GitLab From f433c3b38005701fdc219ae8c01e6af1b8bedba9 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 20 Apr 2024 00:43:36 +0200 Subject: [PATCH 052/357] AMDGPU: Add tests for atomicrmw handling of new metadata (#89248) Add baseline tests which should comprehensively test the new atomic metadata. Test codegen / expansion, and preservation in a few transforms. New metadata defined in #85052 --- .../CodeGen/AMDGPU/flat-atomic-fadd.v2f16.ll | 76 + .../CodeGen/AMDGPU/flat_atomics_i32_system.ll | 2161 ++++++++-- .../CodeGen/AMDGPU/flat_atomics_i64_system.ll | 2268 ++++++++-- llvm/test/CodeGen/AMDGPU/global-atomics-fp.ll | 640 +++ .../AMDGPU/global_atomics_i32_system.ll | 2381 +++++++++-- .../AMDGPU/global_atomics_i64_system.ll | 2328 +++++++++-- .../AMDGPU/global_atomics_scan_fadd.ll | 741 ++++ .../AMDGPU/global_atomics_scan_fmax.ll | 672 +++ .../AMDGPU/global_atomics_scan_fmin.ll | 671 +++ llvm/test/CodeGen/AMDGPU/local-atomics-fp.ll | 710 ++++ .../AMDGPU/expand-atomic-f32-system.ll | 3717 +++++++++++++++++ .../AMDGPU/expand-atomic-f64-system.ll | 1685 ++++++++ .../AMDGPU/expand-atomic-i32-system.ll | 828 ++++ .../AMDGPU/expand-atomic-i64-system.ll | 828 ++++ .../AMDGPU/expand-atomic-rmw-fadd.ll | 2209 +++++++++- .../AMDGPU/expand-atomic-v2bf16-system.ll | 859 ++++ .../AMDGPU/expand-atomic-v2f16-system.ll | 859 ++++ ...expand-atomicrmw-integer-ops-0-to-add-0.ll | 10 + .../InferAddressSpaces/AMDGPU/basic.ll | 10 + .../AMDGPU/inline-atomicrmw-md-preserve.ll | 30 + 20 files changed, 22034 insertions(+), 1649 deletions(-) create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f32-system.ll create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f64-system.ll create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i32-system.ll create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i64-system.ll create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2bf16-system.ll create mode 100644 llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2f16-system.ll create mode 100644 llvm/test/Transforms/Inline/AMDGPU/inline-atomicrmw-md-preserve.ll diff --git a/llvm/test/CodeGen/AMDGPU/flat-atomic-fadd.v2f16.ll b/llvm/test/CodeGen/AMDGPU/flat-atomic-fadd.v2f16.ll index ebd6f18de19d..376fe79f542e 100644 --- a/llvm/test/CodeGen/AMDGPU/flat-atomic-fadd.v2f16.ll +++ b/llvm/test/CodeGen/AMDGPU/flat-atomic-fadd.v2f16.ll @@ -35,3 +35,79 @@ define amdgpu_ps <2 x half> @flat_atomic_fadd_v2f16_rtn_intrinsic(ptr %ptr, <2 x } declare <2 x half> @llvm.amdgcn.flat.atomic.fadd.v2f16.p1.v2f16(ptr, <2 x half>) + +define <2 x half> @flat_agent_atomic_fadd_ret_v2f16(ptr %ptr, <2 x half> %val) { + ; GFX940-LABEL: name: flat_agent_atomic_fadd_ret_v2f16 + ; GFX940: bb.0 (%ir-block.0): + ; GFX940-NEXT: successors: %bb.1(0x80000000) + ; GFX940-NEXT: liveins: $vgpr0, $vgpr1, $vgpr2 + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX940-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX940-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX940-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1 + ; GFX940-NEXT: [[COPY3:%[0-9]+]]:vreg_64_align2 = COPY [[REG_SEQUENCE]] + ; GFX940-NEXT: [[COPY4:%[0-9]+]]:vreg_64_align2 = COPY [[REG_SEQUENCE]] + ; GFX940-NEXT: [[FLAT_LOAD_DWORD:%[0-9]+]]:vgpr_32 = FLAT_LOAD_DWORD [[COPY4]], 0, 0, implicit $exec, implicit $flat_scr :: (load (s32) from %ir.ptr) + ; GFX940-NEXT: [[S_MOV_B64_:%[0-9]+]]:sreg_64 = S_MOV_B64 0 + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: bb.1.atomicrmw.start: + ; GFX940-NEXT: successors: %bb.2(0x04000000), %bb.1(0x7c000000) + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: [[PHI:%[0-9]+]]:sreg_64 = PHI [[S_MOV_B64_]], %bb.0, %4, %bb.1 + ; GFX940-NEXT: [[PHI1:%[0-9]+]]:vgpr_32 = PHI [[FLAT_LOAD_DWORD]], %bb.0, %3, %bb.1 + ; GFX940-NEXT: [[V_PK_ADD_F16_:%[0-9]+]]:vgpr_32 = nofpexcept V_PK_ADD_F16 8, [[PHI1]], 8, [[COPY]], 0, 0, 0, 0, 0, implicit $mode, implicit $exec + ; GFX940-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sreg_64 = REG_SEQUENCE killed [[V_PK_ADD_F16_]], %subreg.sub0, [[PHI1]], %subreg.sub1 + ; GFX940-NEXT: [[COPY5:%[0-9]+]]:vreg_64_align2 = COPY [[REG_SEQUENCE1]] + ; GFX940-NEXT: [[FLAT_ATOMIC_CMPSWAP_RTN:%[0-9]+]]:vgpr_32 = FLAT_ATOMIC_CMPSWAP_RTN [[COPY3]], killed [[COPY5]], 0, 1, implicit $exec, implicit $flat_scr :: (load store syncscope("agent") seq_cst seq_cst (s32) on %ir.ptr) + ; GFX940-NEXT: [[V_CMP_EQ_U32_e64_:%[0-9]+]]:sreg_64 = V_CMP_EQ_U32_e64 [[FLAT_ATOMIC_CMPSWAP_RTN]], [[PHI1]], implicit $exec + ; GFX940-NEXT: [[SI_IF_BREAK:%[0-9]+]]:sreg_64 = SI_IF_BREAK killed [[V_CMP_EQ_U32_e64_]], [[PHI]], implicit-def dead $scc + ; GFX940-NEXT: SI_LOOP [[SI_IF_BREAK]], %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec + ; GFX940-NEXT: S_BRANCH %bb.2 + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: bb.2.atomicrmw.end: + ; GFX940-NEXT: [[PHI2:%[0-9]+]]:vgpr_32 = PHI [[FLAT_ATOMIC_CMPSWAP_RTN]], %bb.1 + ; GFX940-NEXT: [[PHI3:%[0-9]+]]:sreg_64 = PHI [[SI_IF_BREAK]], %bb.1 + ; GFX940-NEXT: SI_END_CF [[PHI3]], implicit-def dead $exec, implicit-def dead $scc, implicit $exec + ; GFX940-NEXT: $vgpr0 = COPY [[PHI2]] + ; GFX940-NEXT: SI_RETURN implicit $vgpr0 + %result = atomicrmw fadd ptr %ptr, <2 x half> %val syncscope("agent") seq_cst + ret <2 x half> %result +} + +define void @flat_agent_atomic_fadd_noret_v2f16(ptr %ptr, <2 x half> %val) { + ; GFX940-LABEL: name: flat_agent_atomic_fadd_noret_v2f16 + ; GFX940: bb.0 (%ir-block.0): + ; GFX940-NEXT: successors: %bb.1(0x80000000) + ; GFX940-NEXT: liveins: $vgpr0, $vgpr1, $vgpr2 + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX940-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX940-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX940-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1 + ; GFX940-NEXT: [[COPY3:%[0-9]+]]:vreg_64_align2 = COPY [[REG_SEQUENCE]] + ; GFX940-NEXT: [[COPY4:%[0-9]+]]:vreg_64_align2 = COPY [[REG_SEQUENCE]] + ; GFX940-NEXT: [[FLAT_LOAD_DWORD:%[0-9]+]]:vgpr_32 = FLAT_LOAD_DWORD [[COPY4]], 0, 0, implicit $exec, implicit $flat_scr :: (load (s32) from %ir.ptr) + ; GFX940-NEXT: [[S_MOV_B64_:%[0-9]+]]:sreg_64 = S_MOV_B64 0 + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: bb.1.atomicrmw.start: + ; GFX940-NEXT: successors: %bb.2(0x04000000), %bb.1(0x7c000000) + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: [[PHI:%[0-9]+]]:sreg_64 = PHI [[S_MOV_B64_]], %bb.0, %4, %bb.1 + ; GFX940-NEXT: [[PHI1:%[0-9]+]]:vgpr_32 = PHI [[FLAT_LOAD_DWORD]], %bb.0, %3, %bb.1 + ; GFX940-NEXT: [[V_PK_ADD_F16_:%[0-9]+]]:vgpr_32 = nofpexcept V_PK_ADD_F16 8, [[PHI1]], 8, [[COPY]], 0, 0, 0, 0, 0, implicit $mode, implicit $exec + ; GFX940-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sreg_64 = REG_SEQUENCE killed [[V_PK_ADD_F16_]], %subreg.sub0, [[PHI1]], %subreg.sub1 + ; GFX940-NEXT: [[COPY5:%[0-9]+]]:vreg_64_align2 = COPY [[REG_SEQUENCE1]] + ; GFX940-NEXT: [[FLAT_ATOMIC_CMPSWAP_RTN:%[0-9]+]]:vgpr_32 = FLAT_ATOMIC_CMPSWAP_RTN [[COPY3]], killed [[COPY5]], 0, 1, implicit $exec, implicit $flat_scr :: (load store syncscope("agent") seq_cst seq_cst (s32) on %ir.ptr) + ; GFX940-NEXT: [[V_CMP_EQ_U32_e64_:%[0-9]+]]:sreg_64 = V_CMP_EQ_U32_e64 [[FLAT_ATOMIC_CMPSWAP_RTN]], [[PHI1]], implicit $exec + ; GFX940-NEXT: [[SI_IF_BREAK:%[0-9]+]]:sreg_64 = SI_IF_BREAK killed [[V_CMP_EQ_U32_e64_]], [[PHI]], implicit-def dead $scc + ; GFX940-NEXT: SI_LOOP [[SI_IF_BREAK]], %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec + ; GFX940-NEXT: S_BRANCH %bb.2 + ; GFX940-NEXT: {{ $}} + ; GFX940-NEXT: bb.2.atomicrmw.end: + ; GFX940-NEXT: [[PHI2:%[0-9]+]]:sreg_64 = PHI [[SI_IF_BREAK]], %bb.1 + ; GFX940-NEXT: SI_END_CF [[PHI2]], implicit-def dead $exec, implicit-def dead $scc, implicit $exec + ; GFX940-NEXT: SI_RETURN + %result = atomicrmw fadd ptr %ptr, <2 x half> %val syncscope("agent") seq_cst + ret void +} diff --git a/llvm/test/CodeGen/AMDGPU/flat_atomics_i32_system.ll b/llvm/test/CodeGen/AMDGPU/flat_atomics_i32_system.ll index 94956511c39d..961273468e75 100644 --- a/llvm/test/CodeGen/AMDGPU/flat_atomics_i32_system.ll +++ b/llvm/test/CodeGen/AMDGPU/flat_atomics_i32_system.ll @@ -287,6 +287,72 @@ define amdgpu_gfx i32 @flat_atomic_xchg_i32_ret_offset_scalar(ptr inreg %out, i3 ret i32 %result } +define void @flat_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_swap v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw xchg ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_swap v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw xchg ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw xchg f32 ; --------------------------------------------------------------------- @@ -571,6 +637,72 @@ define amdgpu_gfx float @flat_atomic_xchg_f32_ret_offset_scalar(ptr inreg %out, ret float %result } +define void @flat_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, float %in) { +; GCN1-LABEL: flat_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_swap v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr float, ptr %out, i64 4 + %tmp0 = atomicrmw xchg ptr %gep, float %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define float @flat_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, float %in) { +; GCN1-LABEL: flat_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_swap v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr float, ptr %out, i64 4 + %result = atomicrmw xchg ptr %gep, float %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %result +} + ; --------------------------------------------------------------------- ; atomicrmw add ; --------------------------------------------------------------------- @@ -855,6 +987,72 @@ define amdgpu_gfx i32 @flat_atomic_add_i32_ret_offset_scalar(ptr inreg %out, i32 ret i32 %result } +define void @flat_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_add v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_add v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_add v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw add ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_add v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_add v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_add v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw add ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw sub ; --------------------------------------------------------------------- @@ -1139,6 +1337,72 @@ define amdgpu_gfx i32 @flat_atomic_sub_i32_ret_offset_scalar(ptr inreg %out, i32 ret i32 %result } +define void @flat_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_sub v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_sub v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_sub v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw sub ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_sub v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_sub v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_sub v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw sub ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw and ; --------------------------------------------------------------------- @@ -1423,61 +1687,127 @@ define amdgpu_gfx i32 @flat_atomic_and_i32_ret_offset_scalar(ptr inreg %out, i32 ret i32 %result } -; --------------------------------------------------------------------- -; atomicrmw nand -; --------------------------------------------------------------------- - -define void @flat_atomic_nand_i32_noret(ptr %ptr, i32 %in) { -; GCN1-LABEL: flat_atomic_nand_i32_noret: +define void @flat_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: flat_load_dword v4, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB40_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_and_b32_e32 v3, v4, v2 -; GCN1-NEXT: v_not_b32_e32 v3, v3 -; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_and v[0:1], v2 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v4, v3 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB40_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: flat_atomic_nand_i32_noret: +; GCN2-LABEL: flat_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN2: ; %bb.0: ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: flat_load_dword v4, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB40_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_and_b32_e32 v3, v4, v2 -; GCN2-NEXT: v_not_b32_e32 v3, v3 -; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_and v[0:1], v2 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v4, v3 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB40_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: flat_atomic_nand_i32_noret: +; GCN3-LABEL: flat_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_and v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw and ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_and v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_and v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_and v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw and ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + +; --------------------------------------------------------------------- +; atomicrmw nand +; --------------------------------------------------------------------- + +define void @flat_atomic_nand_i32_noret(ptr %ptr, i32 %in) { +; GCN1-LABEL: flat_atomic_nand_i32_noret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB50_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_and_b32_e32 v3, v4, v2 +; GCN1-NEXT: v_not_b32_e32 v3, v3 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB50_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: flat_atomic_nand_i32_noret: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB50_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_and_b32_e32 v3, v4, v2 +; GCN2-NEXT: v_not_b32_e32 v3, v3 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB50_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: flat_atomic_nand_i32_noret: ; GCN3: ; %bb.0: ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB40_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB50_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1489,7 +1819,7 @@ define void @flat_atomic_nand_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB40_1 +; GCN3-NEXT: s_cbranch_execnz .LBB50_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] @@ -1505,7 +1835,7 @@ define void @flat_atomic_nand_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB41_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB51_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1517,7 +1847,7 @@ define void @flat_atomic_nand_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB41_1 +; GCN1-NEXT: s_cbranch_execnz .LBB51_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] @@ -1529,7 +1859,7 @@ define void @flat_atomic_nand_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB41_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB51_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1541,7 +1871,7 @@ define void @flat_atomic_nand_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB41_1 +; GCN2-NEXT: s_cbranch_execnz .LBB51_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] @@ -1551,7 +1881,7 @@ define void @flat_atomic_nand_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB41_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB51_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1563,7 +1893,7 @@ define void @flat_atomic_nand_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB41_1 +; GCN3-NEXT: s_cbranch_execnz .LBB51_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] @@ -1578,7 +1908,7 @@ define i32 @flat_atomic_nand_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB42_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB52_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 v4, v3 @@ -1590,7 +1920,7 @@ define i32 @flat_atomic_nand_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB42_1 +; GCN1-NEXT: s_cbranch_execnz .LBB52_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v0, v3 @@ -1601,7 +1931,7 @@ define i32 @flat_atomic_nand_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB42_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB52_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 v4, v3 @@ -1613,7 +1943,7 @@ define i32 @flat_atomic_nand_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB42_1 +; GCN2-NEXT: s_cbranch_execnz .LBB52_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v0, v3 @@ -1624,7 +1954,7 @@ define i32 @flat_atomic_nand_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB42_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB52_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 v4, v3 @@ -1636,7 +1966,7 @@ define i32 @flat_atomic_nand_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB42_1 +; GCN3-NEXT: s_cbranch_execnz .LBB52_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -1653,7 +1983,7 @@ define i32 @flat_atomic_nand_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v0, v[3:4] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB43_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB53_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 v1, v0 @@ -1665,7 +1995,7 @@ define i32 @flat_atomic_nand_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB43_1 +; GCN1-NEXT: s_cbranch_execnz .LBB53_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] @@ -1677,7 +2007,7 @@ define i32 @flat_atomic_nand_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v0, v[3:4] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB43_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB53_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 v1, v0 @@ -1689,7 +2019,7 @@ define i32 @flat_atomic_nand_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB43_1 +; GCN2-NEXT: s_cbranch_execnz .LBB53_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] @@ -1699,7 +2029,7 @@ define i32 @flat_atomic_nand_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB43_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB53_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 v4, v3 @@ -1711,7 +2041,7 @@ define i32 @flat_atomic_nand_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB43_1 +; GCN3-NEXT: s_cbranch_execnz .LBB53_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -1729,7 +2059,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN1-NEXT: v_mov_b32_e32 v1, s5 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB44_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB54_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_and_b32_e32 v2, s6, v3 @@ -1741,7 +2071,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB44_1 +; GCN1-NEXT: s_cbranch_execnz .LBB54_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] @@ -1753,7 +2083,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN2-NEXT: v_mov_b32_e32 v1, s5 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB44_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB54_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v2, s6, v3 @@ -1765,7 +2095,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB44_1 +; GCN2-NEXT: s_cbranch_execnz .LBB54_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] @@ -1777,7 +2107,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB44_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB54_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v2, s6, v3 @@ -1789,7 +2119,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB44_1 +; GCN3-NEXT: s_cbranch_execnz .LBB54_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] @@ -1807,7 +2137,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: v_mov_b32_e32 v1, s35 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB45_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB55_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_and_b32_e32 v2, s6, v3 @@ -1819,7 +2149,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB45_1 +; GCN1-NEXT: s_cbranch_execnz .LBB55_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] @@ -1833,7 +2163,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: v_mov_b32_e32 v1, s35 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB45_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB55_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v2, s6, v3 @@ -1845,7 +2175,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB45_1 +; GCN2-NEXT: s_cbranch_execnz .LBB55_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] @@ -1857,7 +2187,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB45_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB55_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v2, s6, v3 @@ -1869,7 +2199,7 @@ define amdgpu_gfx void @flat_atomic_nand_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB45_1 +; GCN3-NEXT: s_cbranch_execnz .LBB55_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] @@ -1888,7 +2218,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_mov_b32_e32 v1, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v2, s5 -; GCN1-NEXT: .LBB46_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB56_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 v4, v0 @@ -1900,7 +2230,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB46_1 +; GCN1-NEXT: s_cbranch_execnz .LBB56_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] @@ -1914,7 +2244,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_mov_b32_e32 v1, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v2, s5 -; GCN2-NEXT: .LBB46_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB56_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 v4, v0 @@ -1926,7 +2256,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB46_1 +; GCN2-NEXT: s_cbranch_execnz .LBB56_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] @@ -1940,7 +2270,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB46_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB56_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 v4, v0 @@ -1952,7 +2282,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB46_1 +; GCN3-NEXT: s_cbranch_execnz .LBB56_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] @@ -1970,7 +2300,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN1-NEXT: v_mov_b32_e32 v2, s35 ; GCN1-NEXT: flat_load_dword v0, v[1:2] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB47_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB57_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 v4, v0 @@ -1982,7 +2312,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB47_1 +; GCN1-NEXT: s_cbranch_execnz .LBB57_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] @@ -1996,7 +2326,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN2-NEXT: v_mov_b32_e32 v2, s35 ; GCN2-NEXT: flat_load_dword v0, v[1:2] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB47_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB57_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 v4, v0 @@ -2008,7 +2338,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB47_1 +; GCN2-NEXT: s_cbranch_execnz .LBB57_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] @@ -2022,7 +2352,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB47_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB57_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 v4, v0 @@ -2034,7 +2364,7 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB47_1 +; GCN3-NEXT: s_cbranch_execnz .LBB57_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] @@ -2043,6 +2373,157 @@ define amdgpu_gfx i32 @flat_atomic_nand_i32_ret_offset_scalar(ptr inreg %out, i3 ret i32 %result } +define void @flat_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB58_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_and_b32_e32 v3, v4, v2 +; GCN1-NEXT: v_not_b32_e32 v3, v3 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB58_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: flat_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB58_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_and_b32_e32 v3, v4, v2 +; GCN2-NEXT: v_not_b32_e32 v3, v3 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB58_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: flat_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB58_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_and_b32_e32 v3, v4, v2 +; GCN3-NEXT: v_not_b32_e32 v3, v3 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB58_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] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw nand ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v3, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v0, v[3:4] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB59_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 v1, v0 +; GCN1-NEXT: v_and_b32_e32 v0, v1, v2 +; GCN1-NEXT: v_not_b32_e32 v0, v0 +; GCN1-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB59_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: flat_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v0, v[3:4] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB59_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 v1, v0 +; GCN2-NEXT: v_and_b32_e32 v0, v1, v2 +; GCN2-NEXT: v_not_b32_e32 v0, v0 +; GCN2-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB59_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: flat_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB59_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 v4, v3 +; GCN3-NEXT: v_and_b32_e32 v3, v4, v2 +; GCN3-NEXT: v_not_b32_e32 v3, v3 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; 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 .LBB59_1 +; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end +; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v0, v3 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw nand ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw or ; --------------------------------------------------------------------- @@ -2327,84 +2808,150 @@ define amdgpu_gfx i32 @flat_atomic_or_i32_ret_offset_scalar(ptr inreg %out, i32 ret i32 %result } -; --------------------------------------------------------------------- -; atomicrmw xor -; --------------------------------------------------------------------- - -define void @flat_atomic_xor_i32_noret(ptr %ptr, i32 %in) { -; GCN1-LABEL: flat_atomic_xor_i32_noret: +define void @flat_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: flat_atomic_xor v[0:1], v2 +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_or v[0:1], v2 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol ; GCN1-NEXT: s_setpc_b64 s[30:31] ; -; GCN2-LABEL: flat_atomic_xor_i32_noret: +; GCN2-LABEL: flat_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN2: ; %bb.0: ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: flat_atomic_xor v[0:1], v2 +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_or v[0:1], v2 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol ; GCN2-NEXT: s_setpc_b64 s[30:31] ; -; GCN3-LABEL: flat_atomic_xor_i32_noret: +; GCN3-LABEL: flat_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN3: ; %bb.0: ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: flat_atomic_xor v[0:1], v2 +; GCN3-NEXT: flat_atomic_or v[0:1], v2 offset:16 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: buffer_wbinvl1_vol ; GCN3-NEXT: s_setpc_b64 s[30:31] - %tmp0 = atomicrmw xor ptr %ptr, i32 %in seq_cst + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw or ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret void } -define void @flat_atomic_xor_i32_noret_offset(ptr %out, i32 %in) { -; GCN1-LABEL: flat_atomic_xor_i32_noret_offset: +define i32 @flat_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 ; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN1-NEXT: flat_atomic_xor v[0:1], v2 +; GCN1-NEXT: flat_atomic_or v0, v[0:1], v2 glc ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol ; GCN1-NEXT: s_setpc_b64 s[30:31] ; -; GCN2-LABEL: flat_atomic_xor_i32_noret_offset: +; GCN2-LABEL: flat_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access: ; 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: flat_atomic_xor v[0:1], v2 +; GCN2-NEXT: flat_atomic_or v0, v[0:1], v2 glc ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol ; GCN2-NEXT: s_setpc_b64 s[30:31] ; -; GCN3-LABEL: flat_atomic_xor_i32_noret_offset: +; GCN3-LABEL: flat_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access: ; GCN3: ; %bb.0: ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: flat_atomic_xor v[0:1], v2 offset:16 +; GCN3-NEXT: flat_atomic_or v0, v[0:1], v2 offset:16 glc ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: buffer_wbinvl1_vol ; GCN3-NEXT: s_setpc_b64 s[30:31] - %gep = getelementptr i32, ptr %out, i32 4 - %tmp0 = atomicrmw xor ptr %gep, i32 %in seq_cst - ret void + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw or ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result } -define i32 @flat_atomic_xor_i32_ret(ptr %ptr, i32 %in) { -; GCN1-LABEL: flat_atomic_xor_i32_ret: +; --------------------------------------------------------------------- +; atomicrmw xor +; --------------------------------------------------------------------- + +define void @flat_atomic_xor_i32_noret(ptr %ptr, i32 %in) { +; GCN1-LABEL: flat_atomic_xor_i32_noret: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: flat_atomic_xor v0, v[0:1], v2 glc +; GCN1-NEXT: flat_atomic_xor v[0:1], v2 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol ; GCN1-NEXT: s_setpc_b64 s[30:31] ; -; GCN2-LABEL: flat_atomic_xor_i32_ret: +; GCN2-LABEL: flat_atomic_xor_i32_noret: ; GCN2: ; %bb.0: ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: flat_atomic_xor v0, v[0:1], v2 glc +; GCN2-NEXT: flat_atomic_xor v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xor_i32_noret: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_xor v[0:1], v2 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %tmp0 = atomicrmw xor ptr %ptr, i32 %in seq_cst + ret void +} + +define void @flat_atomic_xor_i32_noret_offset(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_xor_i32_noret_offset: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_xor v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xor_i32_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: flat_atomic_xor v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xor_i32_noret_offset: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_xor v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i32 4 + %tmp0 = atomicrmw xor ptr %gep, i32 %in seq_cst + ret void +} + +define i32 @flat_atomic_xor_i32_ret(ptr %ptr, i32 %in) { +; GCN1-LABEL: flat_atomic_xor_i32_ret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: flat_atomic_xor v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xor_i32_ret: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: flat_atomic_xor v0, v[0:1], v2 glc ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol ; GCN2-NEXT: s_setpc_b64 s[30:31] @@ -2611,6 +3158,72 @@ define amdgpu_gfx i32 @flat_atomic_xor_i32_ret_offset_scalar(ptr inreg %out, i32 ret i32 %result } +define void @flat_xor_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_xor_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_xor v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_xor_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_xor v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_xor_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_xor v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw xor ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_xor v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_xor v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_xor v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw xor ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw max ; --------------------------------------------------------------------- @@ -2621,7 +3234,7 @@ define void @flat_atomic_max_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB64_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB80_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_i32_e32 v3, v4, v2 @@ -2632,7 +3245,7 @@ define void @flat_atomic_max_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB64_1 +; GCN1-NEXT: s_cbranch_execnz .LBB80_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] @@ -2642,7 +3255,7 @@ define void @flat_atomic_max_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB64_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB80_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_i32_e32 v3, v4, v2 @@ -2653,7 +3266,7 @@ define void @flat_atomic_max_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB64_1 +; GCN2-NEXT: s_cbranch_execnz .LBB80_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] @@ -2663,7 +3276,7 @@ define void @flat_atomic_max_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB64_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB80_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_i32_e32 v3, v4, v2 @@ -2674,7 +3287,7 @@ define void @flat_atomic_max_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB64_1 +; GCN3-NEXT: s_cbranch_execnz .LBB80_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] @@ -2690,7 +3303,7 @@ define void @flat_atomic_max_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB65_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB81_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_i32_e32 v3, v4, v2 @@ -2701,7 +3314,7 @@ define void @flat_atomic_max_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB65_1 +; GCN1-NEXT: s_cbranch_execnz .LBB81_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] @@ -2713,7 +3326,7 @@ define void @flat_atomic_max_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB65_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB81_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_i32_e32 v3, v4, v2 @@ -2724,7 +3337,7 @@ define void @flat_atomic_max_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB65_1 +; GCN2-NEXT: s_cbranch_execnz .LBB81_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] @@ -2734,7 +3347,7 @@ define void @flat_atomic_max_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB65_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB81_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_i32_e32 v3, v4, v2 @@ -2745,7 +3358,7 @@ define void @flat_atomic_max_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB65_1 +; GCN3-NEXT: s_cbranch_execnz .LBB81_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] @@ -2760,7 +3373,7 @@ define i32 @flat_atomic_max_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB66_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB82_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 v4, v3 @@ -2771,7 +3384,7 @@ define i32 @flat_atomic_max_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB66_1 +; GCN1-NEXT: s_cbranch_execnz .LBB82_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v0, v3 @@ -2782,7 +3395,7 @@ define i32 @flat_atomic_max_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB66_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB82_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 v4, v3 @@ -2793,7 +3406,7 @@ define i32 @flat_atomic_max_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB66_1 +; GCN2-NEXT: s_cbranch_execnz .LBB82_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v0, v3 @@ -2804,7 +3417,7 @@ define i32 @flat_atomic_max_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB66_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB82_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 v4, v3 @@ -2815,7 +3428,7 @@ define i32 @flat_atomic_max_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB66_1 +; GCN3-NEXT: s_cbranch_execnz .LBB82_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -2832,7 +3445,7 @@ define i32 @flat_atomic_max_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v0, v[3:4] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB67_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB83_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 v1, v0 @@ -2843,7 +3456,7 @@ define i32 @flat_atomic_max_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB67_1 +; GCN1-NEXT: s_cbranch_execnz .LBB83_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] @@ -2855,7 +3468,7 @@ define i32 @flat_atomic_max_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v0, v[3:4] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB67_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB83_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 v1, v0 @@ -2866,7 +3479,7 @@ define i32 @flat_atomic_max_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB67_1 +; GCN2-NEXT: s_cbranch_execnz .LBB83_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] @@ -2876,7 +3489,7 @@ define i32 @flat_atomic_max_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB67_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB83_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 v4, v3 @@ -2887,7 +3500,7 @@ define i32 @flat_atomic_max_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB67_1 +; GCN3-NEXT: s_cbranch_execnz .LBB83_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -2905,7 +3518,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN1-NEXT: v_mov_b32_e32 v1, s5 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB68_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB84_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_i32_e32 v2, s6, v3 @@ -2916,7 +3529,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB68_1 +; GCN1-NEXT: s_cbranch_execnz .LBB84_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] @@ -2928,7 +3541,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN2-NEXT: v_mov_b32_e32 v1, s5 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB68_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB84_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_i32_e32 v2, s6, v3 @@ -2939,7 +3552,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB68_1 +; GCN2-NEXT: s_cbranch_execnz .LBB84_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] @@ -2951,7 +3564,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB68_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB84_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_i32_e32 v2, s6, v3 @@ -2962,7 +3575,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB68_1 +; GCN3-NEXT: s_cbranch_execnz .LBB84_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] @@ -2980,7 +3593,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: v_mov_b32_e32 v1, s35 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB69_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB85_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_i32_e32 v2, s6, v3 @@ -2991,7 +3604,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB69_1 +; GCN1-NEXT: s_cbranch_execnz .LBB85_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] @@ -3005,7 +3618,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: v_mov_b32_e32 v1, s35 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB69_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB85_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_i32_e32 v2, s6, v3 @@ -3016,7 +3629,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB69_1 +; GCN2-NEXT: s_cbranch_execnz .LBB85_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] @@ -3028,7 +3641,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB69_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB85_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_i32_e32 v2, s6, v3 @@ -3039,7 +3652,7 @@ define amdgpu_gfx void @flat_atomic_max_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB69_1 +; GCN3-NEXT: s_cbranch_execnz .LBB85_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] @@ -3058,7 +3671,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_mov_b32_e32 v1, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v2, s5 -; GCN1-NEXT: .LBB70_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB86_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 v4, v0 @@ -3069,7 +3682,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB70_1 +; GCN1-NEXT: s_cbranch_execnz .LBB86_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] @@ -3083,7 +3696,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_mov_b32_e32 v1, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v2, s5 -; GCN2-NEXT: .LBB70_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB86_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 v4, v0 @@ -3094,7 +3707,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB70_1 +; GCN2-NEXT: s_cbranch_execnz .LBB86_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] @@ -3108,7 +3721,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB70_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB86_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 v4, v0 @@ -3119,7 +3732,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB70_1 +; GCN3-NEXT: s_cbranch_execnz .LBB86_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] @@ -3137,7 +3750,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN1-NEXT: v_mov_b32_e32 v2, s35 ; GCN1-NEXT: flat_load_dword v0, v[1:2] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB71_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB87_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 v4, v0 @@ -3148,7 +3761,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB71_1 +; GCN1-NEXT: s_cbranch_execnz .LBB87_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] @@ -3162,7 +3775,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN2-NEXT: v_mov_b32_e32 v2, s35 ; GCN2-NEXT: flat_load_dword v0, v[1:2] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB71_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB87_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 v4, v0 @@ -3173,7 +3786,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB71_1 +; GCN2-NEXT: s_cbranch_execnz .LBB87_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] @@ -3187,7 +3800,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB71_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB87_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 v4, v0 @@ -3198,7 +3811,7 @@ define amdgpu_gfx i32 @flat_atomic_max_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB71_1 +; GCN3-NEXT: s_cbranch_execnz .LBB87_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] @@ -3223,7 +3836,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB72_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB88_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_i32_e32 v2, s2, v3 @@ -3234,7 +3847,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB72_1 +; GCN1-NEXT: s_cbranch_execnz .LBB88_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -3253,7 +3866,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB72_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB88_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_i32_e32 v2, s2, v3 @@ -3264,7 +3877,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB72_1 +; GCN2-NEXT: s_cbranch_execnz .LBB88_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -3281,7 +3894,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB72_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB88_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_i32_e32 v2, s2, v3 @@ -3292,7 +3905,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB72_1 +; GCN3-NEXT: s_cbranch_execnz .LBB88_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -3319,7 +3932,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v2, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB73_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB89_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, v2 @@ -3330,7 +3943,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB73_1 +; GCN1-NEXT: s_cbranch_execnz .LBB89_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -3354,7 +3967,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v2, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB73_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB89_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, v2 @@ -3365,7 +3978,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB73_1 +; GCN2-NEXT: s_cbranch_execnz .LBB89_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -3387,7 +4000,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v2, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB73_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB89_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, v2 @@ -3398,7 +4011,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB73_1 +; GCN3-NEXT: s_cbranch_execnz .LBB89_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s6 @@ -3427,7 +4040,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr %out, i32 %in, i32 %index) ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB74_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB90_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_i32_e32 v2, s2, v3 @@ -3438,7 +4051,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr %out, i32 %in, i32 %index) ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB74_1 +; GCN1-NEXT: s_cbranch_execnz .LBB90_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -3455,7 +4068,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr %out, i32 %in, i32 %index) ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB74_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB90_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_i32_e32 v2, s2, v3 @@ -3466,7 +4079,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr %out, i32 %in, i32 %index) ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB74_1 +; GCN2-NEXT: s_cbranch_execnz .LBB90_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -3483,7 +4096,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr %out, i32 %in, i32 %index) ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB74_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB90_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_i32_e32 v2, s2, v3 @@ -3494,7 +4107,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr %out, i32 %in, i32 %index) ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB74_1 +; GCN3-NEXT: s_cbranch_execnz .LBB90_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -3518,7 +4131,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v2, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB75_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB91_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, v2 @@ -3529,7 +4142,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB75_1 +; GCN1-NEXT: s_cbranch_execnz .LBB91_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -3551,7 +4164,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v2, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB75_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB91_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, v2 @@ -3562,7 +4175,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB75_1 +; GCN2-NEXT: s_cbranch_execnz .LBB91_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -3584,7 +4197,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v2, v[0:1] ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB75_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB91_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, v2 @@ -3595,7 +4208,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB75_1 +; GCN3-NEXT: s_cbranch_execnz .LBB91_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s6 @@ -3609,20 +4222,18 @@ entry: ret void } -; --------------------------------------------------------------------- -; atomicrmw umax -; --------------------------------------------------------------------- - -define void @flat_atomic_umax_i32_noret(ptr %ptr, i32 %in) { -; GCN1-LABEL: flat_atomic_umax_i32_noret: +define void @flat_max_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_max_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB76_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB92_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN1-NEXT: v_max_i32_e32 v3, v4, v2 ; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol @@ -3630,20 +4241,22 @@ define void @flat_atomic_umax_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB76_1 +; GCN1-NEXT: s_cbranch_execnz .LBB92_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: flat_atomic_umax_i32_noret: +; GCN2-LABEL: flat_max_i32_noret_offset__amdgpu_no_remote_memory_access: ; 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: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB76_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB92_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN2-NEXT: v_max_i32_e32 v3, v4, v2 ; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol @@ -3651,91 +4264,236 @@ define void @flat_atomic_umax_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB76_1 +; GCN2-NEXT: s_cbranch_execnz .LBB92_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: flat_atomic_umax_i32_noret: +; GCN3-LABEL: flat_max_i32_noret_offset__amdgpu_no_remote_memory_access: ; GCN3: ; %bb.0: ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: flat_load_dword v4, v[0:1] +; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB76_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB92_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_max_u32_e32 v3, v4, v2 -; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN3-NEXT: v_max_i32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: buffer_wbinvl1_vol ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB76_1 +; GCN3-NEXT: s_cbranch_execnz .LBB92_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] - %tmp0 = atomicrmw umax ptr %ptr, i32 %in seq_cst + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw max ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret void } -define void @flat_atomic_umax_i32_noret_offset(ptr %out, i32 %in) { -; GCN1-LABEL: flat_atomic_umax_i32_noret_offset: +define i32 @flat_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: v_add_i32_e32 v3, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v0, v[3:4] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB77_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB93_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_max_u32_e32 v3, v4, v2 -; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: v_mov_b32_e32 v1, v0 +; GCN1-NEXT: v_max_i32_e32 v0, v1, v2 +; GCN1-NEXT: flat_atomic_cmpswap v0, v[3:4], 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, v3, v4 +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB77_1 +; GCN1-NEXT: s_cbranch_execnz .LBB93_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: flat_atomic_umax_i32_noret_offset: +; GCN2-LABEL: flat_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access: ; 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: flat_load_dword v4, v[0:1] +; GCN2-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v0, v[3:4] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB77_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB93_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_max_u32_e32 v3, v4, v2 -; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: v_mov_b32_e32 v1, v0 +; GCN2-NEXT: v_max_i32_e32 v0, v1, v2 +; GCN2-NEXT: flat_atomic_cmpswap v0, v[3:4], 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, v3, v4 +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB77_1 +; GCN2-NEXT: s_cbranch_execnz .LBB93_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: flat_atomic_umax_i32_noret_offset: +; GCN3-LABEL: flat_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access: ; GCN3: ; %bb.0: ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 +; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB77_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB93_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: v_max_i32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; 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 .LBB93_1 +; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end +; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v0, v3 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw max ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + +; --------------------------------------------------------------------- +; atomicrmw umax +; --------------------------------------------------------------------- + +define void @flat_atomic_umax_i32_noret(ptr %ptr, i32 %in) { +; GCN1-LABEL: flat_atomic_umax_i32_noret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB94_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: flat_atomic_umax_i32_noret: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB94_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: flat_atomic_umax_i32_noret: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v4, v[0:1] +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB94_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] + %tmp0 = atomicrmw umax ptr %ptr, i32 %in seq_cst + ret void +} + +define void @flat_atomic_umax_i32_noret_offset(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_umax_i32_noret_offset: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB95_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: flat_atomic_umax_i32_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: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB95_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: flat_atomic_umax_i32_noret_offset: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_max_u32_e32 v3, v4, v2 ; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: buffer_wbinvl1_vol @@ -3743,7 +4501,7 @@ define void @flat_atomic_umax_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB77_1 +; GCN3-NEXT: s_cbranch_execnz .LBB95_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] @@ -3758,7 +4516,7 @@ define i32 @flat_atomic_umax_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB78_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB96_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 v4, v3 @@ -3769,7 +4527,7 @@ define i32 @flat_atomic_umax_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB78_1 +; GCN1-NEXT: s_cbranch_execnz .LBB96_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v0, v3 @@ -3780,7 +4538,7 @@ define i32 @flat_atomic_umax_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB78_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB96_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 v4, v3 @@ -3791,7 +4549,7 @@ define i32 @flat_atomic_umax_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB78_1 +; GCN2-NEXT: s_cbranch_execnz .LBB96_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v0, v3 @@ -3802,7 +4560,7 @@ define i32 @flat_atomic_umax_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB78_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB96_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 v4, v3 @@ -3813,7 +4571,7 @@ define i32 @flat_atomic_umax_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB78_1 +; GCN3-NEXT: s_cbranch_execnz .LBB96_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -3830,7 +4588,7 @@ define i32 @flat_atomic_umax_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v0, v[3:4] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB79_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB97_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 v1, v0 @@ -3841,7 +4599,7 @@ define i32 @flat_atomic_umax_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB79_1 +; GCN1-NEXT: s_cbranch_execnz .LBB97_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] @@ -3853,7 +4611,7 @@ define i32 @flat_atomic_umax_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v0, v[3:4] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB79_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB97_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 v1, v0 @@ -3864,7 +4622,7 @@ define i32 @flat_atomic_umax_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB79_1 +; GCN2-NEXT: s_cbranch_execnz .LBB97_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] @@ -3874,7 +4632,7 @@ define i32 @flat_atomic_umax_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB79_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB97_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 v4, v3 @@ -3885,7 +4643,7 @@ define i32 @flat_atomic_umax_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB79_1 +; GCN3-NEXT: s_cbranch_execnz .LBB97_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -3903,7 +4661,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN1-NEXT: v_mov_b32_e32 v1, s5 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB80_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB98_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_u32_e32 v2, s6, v3 @@ -3914,7 +4672,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB80_1 +; GCN1-NEXT: s_cbranch_execnz .LBB98_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] @@ -3926,7 +4684,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN2-NEXT: v_mov_b32_e32 v1, s5 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB80_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB98_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_u32_e32 v2, s6, v3 @@ -3937,7 +4695,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB80_1 +; GCN2-NEXT: s_cbranch_execnz .LBB98_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] @@ -3949,7 +4707,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB80_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB98_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_u32_e32 v2, s6, v3 @@ -3960,7 +4718,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB80_1 +; GCN3-NEXT: s_cbranch_execnz .LBB98_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] @@ -3978,7 +4736,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: v_mov_b32_e32 v1, s35 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB81_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB99_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_u32_e32 v2, s6, v3 @@ -3989,7 +4747,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB81_1 +; GCN1-NEXT: s_cbranch_execnz .LBB99_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] @@ -4003,7 +4761,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: v_mov_b32_e32 v1, s35 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB81_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB99_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_u32_e32 v2, s6, v3 @@ -4014,7 +4772,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB81_1 +; GCN2-NEXT: s_cbranch_execnz .LBB99_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] @@ -4026,7 +4784,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB81_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB99_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_u32_e32 v2, s6, v3 @@ -4037,7 +4795,7 @@ define amdgpu_gfx void @flat_atomic_umax_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB81_1 +; GCN3-NEXT: s_cbranch_execnz .LBB99_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] @@ -4056,7 +4814,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_mov_b32_e32 v1, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v2, s5 -; GCN1-NEXT: .LBB82_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB100_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 v4, v0 @@ -4067,7 +4825,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB82_1 +; GCN1-NEXT: s_cbranch_execnz .LBB100_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] @@ -4081,7 +4839,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_mov_b32_e32 v1, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v2, s5 -; GCN2-NEXT: .LBB82_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB100_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 v4, v0 @@ -4092,7 +4850,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB82_1 +; GCN2-NEXT: s_cbranch_execnz .LBB100_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] @@ -4106,7 +4864,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB82_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB100_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 v4, v0 @@ -4117,7 +4875,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB82_1 +; GCN3-NEXT: s_cbranch_execnz .LBB100_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] @@ -4135,7 +4893,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN1-NEXT: v_mov_b32_e32 v2, s35 ; GCN1-NEXT: flat_load_dword v0, v[1:2] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB83_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB101_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 v4, v0 @@ -4146,7 +4904,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB83_1 +; GCN1-NEXT: s_cbranch_execnz .LBB101_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] @@ -4160,7 +4918,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN2-NEXT: v_mov_b32_e32 v2, s35 ; GCN2-NEXT: flat_load_dword v0, v[1:2] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB83_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB101_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 v4, v0 @@ -4171,7 +4929,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB83_1 +; GCN2-NEXT: s_cbranch_execnz .LBB101_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] @@ -4185,7 +4943,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB83_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB101_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 v4, v0 @@ -4196,7 +4954,7 @@ define amdgpu_gfx i32 @flat_atomic_umax_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB83_1 +; GCN3-NEXT: s_cbranch_execnz .LBB101_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] @@ -4221,7 +4979,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr %out, i32 %in, i32 ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB84_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB102_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_max_u32_e32 v2, s2, v3 @@ -4232,7 +4990,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr %out, i32 %in, i32 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB84_1 +; GCN1-NEXT: s_cbranch_execnz .LBB102_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -4251,7 +5009,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr %out, i32 %in, i32 ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB84_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB102_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_max_u32_e32 v2, s2, v3 @@ -4262,7 +5020,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr %out, i32 %in, i32 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB84_1 +; GCN2-NEXT: s_cbranch_execnz .LBB102_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -4279,7 +5037,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr %out, i32 %in, i32 ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB84_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB102_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_max_u32_e32 v2, s2, v3 @@ -4290,7 +5048,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr %out, i32 %in, i32 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB84_1 +; GCN3-NEXT: s_cbranch_execnz .LBB102_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -4317,7 +5075,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr %out, ptr %out2 ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v2, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB85_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB103_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, v2 @@ -4328,7 +5086,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr %out, ptr %out2 ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB85_1 +; GCN1-NEXT: s_cbranch_execnz .LBB103_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -4352,7 +5110,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr %out, ptr %out2 ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v2, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB85_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB103_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, v2 @@ -4363,7 +5121,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr %out, ptr %out2 ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB85_1 +; GCN2-NEXT: s_cbranch_execnz .LBB103_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -4385,7 +5143,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr %out, ptr %out2 ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v2, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB85_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB103_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, v2 @@ -4396,7 +5154,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr %out, ptr %out2 ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB85_1 +; GCN3-NEXT: s_cbranch_execnz .LBB103_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s6 @@ -4426,7 +5184,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr %out, ptr %out2, i32 % ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v2, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB86_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB104_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, v2 @@ -4437,7 +5195,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr %out, ptr %out2, i32 % ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB86_1 +; GCN1-NEXT: s_cbranch_execnz .LBB104_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -4459,7 +5217,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr %out, ptr %out2, i32 % ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v2, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB86_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB104_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, v2 @@ -4470,7 +5228,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr %out, ptr %out2, i32 % ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB86_1 +; GCN2-NEXT: s_cbranch_execnz .LBB104_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -4492,29 +5250,174 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr %out, ptr %out2, i32 % ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v2, v[0:1] ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB86_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB104_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, v2 +; GCN3-NEXT: v_max_u32_e32 v2, s2, v3 +; GCN3-NEXT: flat_atomic_cmpswap v2, 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, v2, v3 +; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GCN3-NEXT: s_cbranch_execnz .LBB104_1 +; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end +; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] +; GCN3-NEXT: v_mov_b32_e32 v0, s6 +; GCN3-NEXT: v_mov_b32_e32 v1, s7 +; GCN3-NEXT: flat_store_dword v[0:1], v2 +; GCN3-NEXT: s_endpgm +entry: + %ptr = getelementptr i32, ptr %out, i32 %index + %tmp0 = atomicrmw umax ptr %ptr, i32 %in seq_cst + store i32 %tmp0, ptr %out2 + ret void +} + +define void @flat_umax_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_umax_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB105_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: flat_umax_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB105_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: flat_umax_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB105_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] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw umax ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v3, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v0, v[3:4] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB106_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 v1, v0 +; GCN1-NEXT: v_max_u32_e32 v0, v1, v2 +; GCN1-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB106_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: flat_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v0, v[3:4] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB106_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 v1, v0 +; GCN2-NEXT: v_max_u32_e32 v0, v1, v2 +; GCN2-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB106_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: flat_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB106_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, v2 -; GCN3-NEXT: v_max_u32_e32 v2, s2, v3 -; GCN3-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: v_max_u32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 -; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB86_1 +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; 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 .LBB106_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v1, s7 -; GCN3-NEXT: flat_store_dword v[0:1], v2 -; GCN3-NEXT: s_endpgm -entry: - %ptr = getelementptr i32, ptr %out, i32 %index - %tmp0 = atomicrmw umax ptr %ptr, i32 %in seq_cst - store i32 %tmp0, ptr %out2 - ret void +; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v0, v3 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw umax ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result } ; --------------------------------------------------------------------- @@ -4527,7 +5430,7 @@ define void @flat_atomic_umin_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB87_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB107_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_u32_e32 v3, v4, v2 @@ -4538,7 +5441,7 @@ define void @flat_atomic_umin_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB87_1 +; GCN1-NEXT: s_cbranch_execnz .LBB107_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] @@ -4548,7 +5451,7 @@ define void @flat_atomic_umin_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB87_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB107_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_u32_e32 v3, v4, v2 @@ -4559,7 +5462,7 @@ define void @flat_atomic_umin_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB87_1 +; GCN2-NEXT: s_cbranch_execnz .LBB107_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] @@ -4569,7 +5472,7 @@ define void @flat_atomic_umin_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB87_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB107_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_u32_e32 v3, v4, v2 @@ -4580,7 +5483,7 @@ define void @flat_atomic_umin_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB87_1 +; GCN3-NEXT: s_cbranch_execnz .LBB107_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] @@ -4596,7 +5499,7 @@ define void @flat_atomic_umin_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB88_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB108_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_u32_e32 v3, v4, v2 @@ -4607,7 +5510,7 @@ define void @flat_atomic_umin_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB88_1 +; GCN1-NEXT: s_cbranch_execnz .LBB108_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] @@ -4619,7 +5522,7 @@ define void @flat_atomic_umin_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB88_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB108_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_u32_e32 v3, v4, v2 @@ -4630,7 +5533,7 @@ define void @flat_atomic_umin_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB88_1 +; GCN2-NEXT: s_cbranch_execnz .LBB108_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] @@ -4640,7 +5543,7 @@ define void @flat_atomic_umin_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB88_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB108_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_u32_e32 v3, v4, v2 @@ -4651,7 +5554,7 @@ define void @flat_atomic_umin_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB88_1 +; GCN3-NEXT: s_cbranch_execnz .LBB108_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] @@ -4666,7 +5569,7 @@ define i32 @flat_atomic_umin_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB89_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB109_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 v4, v3 @@ -4677,7 +5580,7 @@ define i32 @flat_atomic_umin_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB89_1 +; GCN1-NEXT: s_cbranch_execnz .LBB109_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v0, v3 @@ -4688,7 +5591,7 @@ define i32 @flat_atomic_umin_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB89_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB109_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 v4, v3 @@ -4699,7 +5602,7 @@ define i32 @flat_atomic_umin_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB89_1 +; GCN2-NEXT: s_cbranch_execnz .LBB109_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v0, v3 @@ -4710,7 +5613,7 @@ define i32 @flat_atomic_umin_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB89_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB109_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 v4, v3 @@ -4721,7 +5624,7 @@ define i32 @flat_atomic_umin_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB89_1 +; GCN3-NEXT: s_cbranch_execnz .LBB109_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -4738,7 +5641,7 @@ define i32 @flat_atomic_umin_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v0, v[3:4] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB90_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB110_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 v1, v0 @@ -4749,7 +5652,7 @@ define i32 @flat_atomic_umin_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB90_1 +; GCN1-NEXT: s_cbranch_execnz .LBB110_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] @@ -4761,7 +5664,7 @@ define i32 @flat_atomic_umin_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v0, v[3:4] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB90_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB110_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 v1, v0 @@ -4772,7 +5675,7 @@ define i32 @flat_atomic_umin_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB90_1 +; GCN2-NEXT: s_cbranch_execnz .LBB110_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] @@ -4782,7 +5685,7 @@ define i32 @flat_atomic_umin_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB90_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB110_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 v4, v3 @@ -4793,7 +5696,7 @@ define i32 @flat_atomic_umin_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB90_1 +; GCN3-NEXT: s_cbranch_execnz .LBB110_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -4811,7 +5714,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN1-NEXT: v_mov_b32_e32 v1, s5 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB91_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB111_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_u32_e32 v2, s6, v3 @@ -4822,7 +5725,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB91_1 +; GCN1-NEXT: s_cbranch_execnz .LBB111_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] @@ -4834,7 +5737,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN2-NEXT: v_mov_b32_e32 v1, s5 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB91_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB111_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_u32_e32 v2, s6, v3 @@ -4845,7 +5748,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB91_1 +; GCN2-NEXT: s_cbranch_execnz .LBB111_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] @@ -4857,7 +5760,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB91_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB111_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_u32_e32 v2, s6, v3 @@ -4868,7 +5771,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_scalar(ptr inreg %ptr, i32 in ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB91_1 +; GCN3-NEXT: s_cbranch_execnz .LBB111_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] @@ -4886,7 +5789,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: v_mov_b32_e32 v1, s35 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB92_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB112_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_u32_e32 v2, s6, v3 @@ -4897,7 +5800,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB92_1 +; GCN1-NEXT: s_cbranch_execnz .LBB112_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] @@ -4911,7 +5814,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: v_mov_b32_e32 v1, s35 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB92_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB112_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_u32_e32 v2, s6, v3 @@ -4922,7 +5825,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB92_1 +; GCN2-NEXT: s_cbranch_execnz .LBB112_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] @@ -4934,7 +5837,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB92_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB112_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_u32_e32 v2, s6, v3 @@ -4945,7 +5848,7 @@ define amdgpu_gfx void @flat_atomic_umin_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB92_1 +; GCN3-NEXT: s_cbranch_execnz .LBB112_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] @@ -4964,7 +5867,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_mov_b32_e32 v1, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v2, s5 -; GCN1-NEXT: .LBB93_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB113_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 v4, v0 @@ -4975,7 +5878,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB93_1 +; GCN1-NEXT: s_cbranch_execnz .LBB113_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] @@ -4989,7 +5892,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_mov_b32_e32 v1, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v2, s5 -; GCN2-NEXT: .LBB93_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB113_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 v4, v0 @@ -5000,7 +5903,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB93_1 +; GCN2-NEXT: s_cbranch_execnz .LBB113_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] @@ -5014,7 +5917,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB93_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB113_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 v4, v0 @@ -5025,7 +5928,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB93_1 +; GCN3-NEXT: s_cbranch_execnz .LBB113_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] @@ -5043,7 +5946,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN1-NEXT: v_mov_b32_e32 v2, s35 ; GCN1-NEXT: flat_load_dword v0, v[1:2] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB114_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 v4, v0 @@ -5054,7 +5957,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB94_1 +; GCN1-NEXT: s_cbranch_execnz .LBB114_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] @@ -5068,7 +5971,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN2-NEXT: v_mov_b32_e32 v2, s35 ; GCN2-NEXT: flat_load_dword v0, v[1:2] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB114_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 v4, v0 @@ -5079,7 +5982,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB94_1 +; GCN2-NEXT: s_cbranch_execnz .LBB114_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] @@ -5093,7 +5996,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB114_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 v4, v0 @@ -5104,7 +6007,7 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB94_1 +; GCN3-NEXT: s_cbranch_execnz .LBB114_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] @@ -5113,6 +6016,151 @@ define amdgpu_gfx i32 @flat_atomic_umin_i32_ret_offset_scalar(ptr inreg %out, i3 ret i32 %result } +define void @flat_umin_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_umin_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB115_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_min_u32_e32 v3, v4, v2 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB115_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: flat_umin_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB115_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_min_u32_e32 v3, v4, v2 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB115_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: flat_umin_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB115_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_min_u32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB115_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] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw umin ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v3, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v0, v[3:4] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB116_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 v1, v0 +; GCN1-NEXT: v_min_u32_e32 v0, v1, v2 +; GCN1-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB116_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: flat_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v0, v[3:4] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB116_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 v1, v0 +; GCN2-NEXT: v_min_u32_e32 v0, v1, v2 +; GCN2-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB116_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: flat_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB116_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 v4, v3 +; GCN3-NEXT: v_min_u32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; 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 .LBB116_1 +; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end +; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v0, v3 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw umin ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw min ; --------------------------------------------------------------------- @@ -5123,7 +6171,7 @@ define void @flat_atomic_min_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB117_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5134,7 +6182,7 @@ define void @flat_atomic_min_i32_noret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB95_1 +; GCN1-NEXT: s_cbranch_execnz .LBB117_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] @@ -5144,7 +6192,7 @@ define void @flat_atomic_min_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB117_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5155,7 +6203,7 @@ define void @flat_atomic_min_i32_noret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB95_1 +; GCN2-NEXT: s_cbranch_execnz .LBB117_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] @@ -5165,7 +6213,7 @@ define void @flat_atomic_min_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB117_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5176,7 +6224,7 @@ define void @flat_atomic_min_i32_noret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB95_1 +; GCN3-NEXT: s_cbranch_execnz .LBB117_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] @@ -5192,7 +6240,7 @@ define void @flat_atomic_min_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB96_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB118_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5203,7 +6251,7 @@ define void @flat_atomic_min_i32_noret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v4, v3 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB96_1 +; GCN1-NEXT: s_cbranch_execnz .LBB118_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] @@ -5215,7 +6263,7 @@ define void @flat_atomic_min_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB96_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB118_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5226,7 +6274,7 @@ define void @flat_atomic_min_i32_noret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v4, v3 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB96_1 +; GCN2-NEXT: s_cbranch_execnz .LBB118_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] @@ -5236,7 +6284,7 @@ define void @flat_atomic_min_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB96_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB118_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_i32_e32 v3, v4, v2 @@ -5247,7 +6295,7 @@ define void @flat_atomic_min_i32_noret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v4, v3 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB96_1 +; GCN3-NEXT: s_cbranch_execnz .LBB118_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] @@ -5262,7 +6310,7 @@ define i32 @flat_atomic_min_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB97_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB119_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 v4, v3 @@ -5273,7 +6321,7 @@ define i32 @flat_atomic_min_i32_ret(ptr %ptr, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB97_1 +; GCN1-NEXT: s_cbranch_execnz .LBB119_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v0, v3 @@ -5284,7 +6332,7 @@ define i32 @flat_atomic_min_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB97_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB119_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 v4, v3 @@ -5295,7 +6343,7 @@ define i32 @flat_atomic_min_i32_ret(ptr %ptr, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB97_1 +; GCN2-NEXT: s_cbranch_execnz .LBB119_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v0, v3 @@ -5306,7 +6354,7 @@ define i32 @flat_atomic_min_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB97_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB119_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 v4, v3 @@ -5317,7 +6365,7 @@ define i32 @flat_atomic_min_i32_ret(ptr %ptr, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB97_1 +; GCN3-NEXT: s_cbranch_execnz .LBB119_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -5334,7 +6382,7 @@ define i32 @flat_atomic_min_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v0, v[3:4] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB98_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB120_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 v1, v0 @@ -5345,7 +6393,7 @@ define i32 @flat_atomic_min_i32_ret_offset(ptr %out, i32 %in) { ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB98_1 +; GCN1-NEXT: s_cbranch_execnz .LBB120_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] @@ -5357,7 +6405,7 @@ define i32 @flat_atomic_min_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; GCN2-NEXT: flat_load_dword v0, v[3:4] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB98_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB120_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 v1, v0 @@ -5368,7 +6416,7 @@ define i32 @flat_atomic_min_i32_ret_offset(ptr %out, i32 %in) { ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; 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 .LBB98_1 +; GCN2-NEXT: s_cbranch_execnz .LBB120_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] @@ -5378,7 +6426,7 @@ define i32 @flat_atomic_min_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB98_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB120_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 v4, v3 @@ -5389,7 +6437,7 @@ define i32 @flat_atomic_min_i32_ret_offset(ptr %out, i32 %in) { ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; 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 .LBB98_1 +; GCN3-NEXT: s_cbranch_execnz .LBB120_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v0, v3 @@ -5407,7 +6455,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN1-NEXT: v_mov_b32_e32 v1, s5 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB99_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB121_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_i32_e32 v2, s6, v3 @@ -5418,7 +6466,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB99_1 +; GCN1-NEXT: s_cbranch_execnz .LBB121_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] @@ -5430,7 +6478,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN2-NEXT: v_mov_b32_e32 v1, s5 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB99_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB121_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_i32_e32 v2, s6, v3 @@ -5441,7 +6489,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB99_1 +; GCN2-NEXT: s_cbranch_execnz .LBB121_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] @@ -5453,7 +6501,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB99_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB121_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_i32_e32 v2, s6, v3 @@ -5464,7 +6512,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_scalar(ptr inreg %ptr, i32 inr ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB99_1 +; GCN3-NEXT: s_cbranch_execnz .LBB121_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] @@ -5482,7 +6530,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: v_mov_b32_e32 v1, s35 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB100_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB122_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_i32_e32 v2, s6, v3 @@ -5493,7 +6541,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB100_1 +; GCN1-NEXT: s_cbranch_execnz .LBB122_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] @@ -5507,7 +6555,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: v_mov_b32_e32 v1, s35 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB100_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB122_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_i32_e32 v2, s6, v3 @@ -5518,7 +6566,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB100_1 +; GCN2-NEXT: s_cbranch_execnz .LBB122_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] @@ -5530,7 +6578,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB100_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB122_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_i32_e32 v2, s6, v3 @@ -5541,7 +6589,7 @@ define amdgpu_gfx void @flat_atomic_min_i32_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB100_1 +; GCN3-NEXT: s_cbranch_execnz .LBB122_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] @@ -5560,7 +6608,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_mov_b32_e32 v1, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v2, s5 -; GCN1-NEXT: .LBB101_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB123_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 v4, v0 @@ -5571,7 +6619,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB101_1 +; GCN1-NEXT: s_cbranch_execnz .LBB123_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] @@ -5585,7 +6633,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_mov_b32_e32 v1, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v2, s5 -; GCN2-NEXT: .LBB101_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB123_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 v4, v0 @@ -5596,7 +6644,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB101_1 +; GCN2-NEXT: s_cbranch_execnz .LBB123_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] @@ -5610,7 +6658,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB101_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB123_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 v4, v0 @@ -5621,7 +6669,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_scalar(ptr inreg %ptr, i32 inreg ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB101_1 +; GCN3-NEXT: s_cbranch_execnz .LBB123_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] @@ -5639,7 +6687,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN1-NEXT: v_mov_b32_e32 v2, s35 ; GCN1-NEXT: flat_load_dword v0, v[1:2] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB102_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB124_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 v4, v0 @@ -5650,7 +6698,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB102_1 +; GCN1-NEXT: s_cbranch_execnz .LBB124_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] @@ -5664,7 +6712,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN2-NEXT: v_mov_b32_e32 v2, s35 ; GCN2-NEXT: flat_load_dword v0, v[1:2] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB102_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB124_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 v4, v0 @@ -5675,7 +6723,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB102_1 +; GCN2-NEXT: s_cbranch_execnz .LBB124_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] @@ -5689,7 +6737,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN3-NEXT: v_mov_b32_e32 v1, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v2, s5 -; GCN3-NEXT: .LBB102_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB124_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 v4, v0 @@ -5700,7 +6748,7 @@ define amdgpu_gfx i32 @flat_atomic_min_i32_ret_offset_scalar(ptr inreg %out, i32 ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; 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 .LBB102_1 +; GCN3-NEXT: s_cbranch_execnz .LBB124_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] @@ -5725,7 +6773,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB103_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB125_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_i32_e32 v2, s2, v3 @@ -5736,7 +6784,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB103_1 +; GCN1-NEXT: s_cbranch_execnz .LBB125_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -5755,7 +6803,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB103_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB125_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_i32_e32 v2, s2, v3 @@ -5766,7 +6814,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB103_1 +; GCN2-NEXT: s_cbranch_execnz .LBB125_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -5783,7 +6831,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB103_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB125_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_i32_e32 v2, s2, v3 @@ -5794,7 +6842,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr %out, i32 %in, i32 % ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB103_1 +; GCN3-NEXT: s_cbranch_execnz .LBB125_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -5821,7 +6869,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v2, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB104_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB126_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, v2 @@ -5832,7 +6880,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB104_1 +; GCN1-NEXT: s_cbranch_execnz .LBB126_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -5856,7 +6904,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v2, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB104_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB126_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, v2 @@ -5867,7 +6915,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB104_1 +; GCN2-NEXT: s_cbranch_execnz .LBB126_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -5889,7 +6937,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v2, v[0:1] offset:16 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB104_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB126_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, v2 @@ -5900,7 +6948,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB104_1 +; GCN3-NEXT: s_cbranch_execnz .LBB126_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s6 @@ -5925,7 +6973,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr %out, i32 %in) { ; GCN1-NEXT: v_mov_b32_e32 v0, s4 ; GCN1-NEXT: v_mov_b32_e32 v1, s5 ; GCN1-NEXT: flat_load_dword v3, v[0:1] -; GCN1-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB127_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_min_i32_e32 v2, s2, v3 @@ -5936,7 +6984,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr %out, i32 %in) { ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v3, v2 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB105_1 +; GCN1-NEXT: s_cbranch_execnz .LBB127_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -5949,7 +6997,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr %out, i32 %in) { ; GCN2-NEXT: v_mov_b32_e32 v0, s4 ; GCN2-NEXT: v_mov_b32_e32 v1, s5 ; GCN2-NEXT: flat_load_dword v3, v[0:1] -; GCN2-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB127_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_min_i32_e32 v2, s2, v3 @@ -5960,7 +7008,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr %out, i32 %in) { ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v3, v2 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB105_1 +; GCN2-NEXT: s_cbranch_execnz .LBB127_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -5973,7 +7021,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr %out, i32 %in) { ; GCN3-NEXT: v_mov_b32_e32 v0, s4 ; GCN3-NEXT: v_mov_b32_e32 v1, s5 ; GCN3-NEXT: flat_load_dword v3, v[0:1] -; GCN3-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB127_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_min_i32_e32 v2, s2, v3 @@ -5984,7 +7032,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr %out, i32 %in) { ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v3, v2 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB105_1 +; GCN3-NEXT: s_cbranch_execnz .LBB127_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -6007,7 +7055,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN1-NEXT: v_mov_b32_e32 v1, s1 ; GCN1-NEXT: flat_load_dword v2, v[0:1] ; GCN1-NEXT: s_mov_b64 s[0:1], 0 -; GCN1-NEXT: .LBB106_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB128_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, v2 @@ -6018,7 +7066,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB106_1 +; GCN1-NEXT: s_cbranch_execnz .LBB128_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -6040,7 +7088,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN2-NEXT: v_mov_b32_e32 v1, s1 ; GCN2-NEXT: flat_load_dword v2, v[0:1] ; GCN2-NEXT: s_mov_b64 s[0:1], 0 -; GCN2-NEXT: .LBB106_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB128_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, v2 @@ -6051,7 +7099,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB106_1 +; GCN2-NEXT: s_cbranch_execnz .LBB128_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -6073,7 +7121,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN3-NEXT: v_mov_b32_e32 v1, s1 ; GCN3-NEXT: flat_load_dword v2, v[0:1] ; GCN3-NEXT: s_mov_b64 s[0:1], 0 -; GCN3-NEXT: .LBB106_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB128_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, v2 @@ -6084,7 +7132,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr %out, ptr %out2, i32 %i ; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB106_1 +; GCN3-NEXT: s_cbranch_execnz .LBB128_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s6 @@ -6098,6 +7146,151 @@ entry: ret void } +define void @flat_min_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_min_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v4, v[0:1] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB129_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_min_i32_e32 v3, v4, v2 +; GCN1-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v4, v3 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB129_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: flat_min_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_load_dword v4, v[0:1] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB129_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_min_i32_e32 v3, v4, v2 +; GCN2-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v4, v3 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB129_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: flat_min_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v4, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB129_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_min_i32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v4, v3 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB129_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] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw min ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v3, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v0, v[3:4] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB130_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 v1, v0 +; GCN1-NEXT: v_min_i32_e32 v0, v1, v2 +; GCN1-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB130_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: flat_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; GCN2-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v0, v[3:4] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB130_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 v1, v0 +; GCN2-NEXT: v_min_i32_e32 v0, v1, v2 +; GCN2-NEXT: flat_atomic_cmpswap v0, v[3:4], 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[4:5], vcc, s[4:5] +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB130_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: flat_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dword v3, v[0:1] offset:16 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB130_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 v4, v3 +; GCN3-NEXT: v_min_i32_e32 v3, v4, v2 +; GCN3-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; 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 .LBB130_1 +; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end +; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v0, v3 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw min ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw uinc_wrap ; --------------------------------------------------------------------- @@ -6382,6 +7575,72 @@ define amdgpu_gfx i32 @flat_atomic_uinc_wrap_i32_ret_offset_scalar(ptr inreg %ou ret i32 %result } +define void @flat_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_inc v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_inc v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_inc v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw uinc_wrap ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_inc v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_inc v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_inc v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw uinc_wrap ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw udec_wrap ; --------------------------------------------------------------------- @@ -6665,3 +7924,71 @@ define amdgpu_gfx i32 @flat_atomic_udec_wrap_i32_ret_offset_scalar(ptr inreg %ou %result = atomicrmw udec_wrap ptr %gep, i32 %in seq_cst ret i32 %result } + +define void @flat_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_dec v[0:1], v2 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_dec v[0:1], v2 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_dec v[0:1], v2 offset:16 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %tmp0 = atomicrmw udec_wrap ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @flat_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i32 %in) { +; GCN1-LABEL: flat_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 16, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_dec v0, v[0:1], v2 glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; 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: flat_atomic_dec v0, v[0:1], v2 glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_dec v0, v[0:1], v2 offset:16 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr %out, i64 4 + %result = atomicrmw udec_wrap ptr %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + +!0 = !{} diff --git a/llvm/test/CodeGen/AMDGPU/flat_atomics_i64_system.ll b/llvm/test/CodeGen/AMDGPU/flat_atomics_i64_system.ll index 7fc4484608c2..4bf3e2fdd051 100644 --- a/llvm/test/CodeGen/AMDGPU/flat_atomics_i64_system.ll +++ b/llvm/test/CodeGen/AMDGPU/flat_atomics_i64_system.ll @@ -299,6 +299,72 @@ define amdgpu_gfx i64 @flat_atomic_xchg_i64_ret_offset_scalar(ptr inreg %out, i6 ret i64 %result } +define void @flat_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw xchg ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw xchg ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw xchg f64 ; --------------------------------------------------------------------- @@ -595,6 +661,72 @@ define amdgpu_gfx double @flat_atomic_xchg_f64_ret_offset_scalar(ptr inreg %out, ret double %result } +define void @flat_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, double %in) { +; GCN1-LABEL: flat_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr double, ptr %out, i64 4 + %tmp0 = atomicrmw xchg ptr %gep, double %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define double @flat_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, double %in) { +; GCN1-LABEL: flat_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr double, ptr %out, i64 4 + %result = atomicrmw xchg ptr %gep, double %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %result +} + ; --------------------------------------------------------------------- ; atomicrmw add ; --------------------------------------------------------------------- @@ -891,6 +1023,72 @@ define amdgpu_gfx i64 @flat_atomic_add_i64_ret_offset_scalar(ptr inreg %out, i64 ret i64 %result } +define void @flat_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_add_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_add_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_add_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw add ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_add_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_add_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_add_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw add ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw sub ; --------------------------------------------------------------------- @@ -1187,6 +1385,72 @@ define amdgpu_gfx i64 @flat_atomic_sub_i64_ret_offset_scalar(ptr inreg %out, i64 ret i64 %result } +define void @flat_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_sub_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_sub_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_sub_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw sub ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_sub_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_sub_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_sub_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw sub ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw and ; --------------------------------------------------------------------- @@ -1483,48 +1747,114 @@ define amdgpu_gfx i64 @flat_atomic_and_i64_ret_offset_scalar(ptr inreg %out, i64 ret i64 %result } -; --------------------------------------------------------------------- -; atomicrmw nand -; --------------------------------------------------------------------- - -define void @flat_atomic_nand_i64_noret(ptr %ptr, i64 %in) { -; GCN1-LABEL: flat_atomic_nand_i64_noret: +define void @flat_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_i32_e32 v4, vcc, 4, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: flat_load_dword v6, v[0:1] -; GCN1-NEXT: flat_load_dword v7, v[4:5] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB40_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_and_b32_e32 v4, v7, v3 -; GCN1-NEXT: v_and_b32_e32 v8, v6, v2 -; GCN1-NEXT: v_not_b32_e32 v5, v4 -; GCN1-NEXT: v_not_b32_e32 v4, v8 -; GCN1-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_and_x2 v[0:1], v[2:3] ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] -; GCN1-NEXT: v_mov_b32_e32 v7, v5 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v6, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB40_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: flat_atomic_nand_i64_noret: +; GCN2-LABEL: flat_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN2: ; %bb.0: ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v4, vcc, 4, v0 -; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN2-NEXT: flat_load_dword v6, v[0:1] -; GCN2-NEXT: flat_load_dword v7, v[4:5] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB40_1: ; %atomicrmw.start +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_and_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_and_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw and ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_and_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_and_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_and_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw and ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw nand +; --------------------------------------------------------------------- + +define void @flat_atomic_nand_i64_noret(ptr %ptr, i64 %in) { +; GCN1-LABEL: flat_atomic_nand_i64_noret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 4, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v6, v[0:1] +; GCN1-NEXT: flat_load_dword v7, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB50_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_and_b32_e32 v4, v7, v3 +; GCN1-NEXT: v_and_b32_e32 v8, v6, v2 +; GCN1-NEXT: v_not_b32_e32 v5, v4 +; GCN1-NEXT: v_not_b32_e32 v4, v8 +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v5 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v6, v4 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB50_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: flat_atomic_nand_i64_noret: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 4, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v6, v[0:1] +; GCN2-NEXT: flat_load_dword v7, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB50_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1539,7 +1869,7 @@ define void @flat_atomic_nand_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v4 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB40_1 +; GCN2-NEXT: s_cbranch_execnz .LBB50_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] @@ -1549,7 +1879,7 @@ define void @flat_atomic_nand_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB40_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB50_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1564,7 +1894,7 @@ define void @flat_atomic_nand_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB40_1 +; GCN3-NEXT: s_cbranch_execnz .LBB50_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] @@ -1583,7 +1913,7 @@ define void @flat_atomic_nand_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v7, v[0:1] ; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB41_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB51_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_and_b32_e32 v0, v7, v3 @@ -1598,7 +1928,7 @@ define void @flat_atomic_nand_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB41_1 +; GCN1-NEXT: s_cbranch_execnz .LBB51_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] @@ -1613,7 +1943,7 @@ define void @flat_atomic_nand_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v7, v[0:1] ; GCN2-NEXT: flat_load_dword v6, v[8:9] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB41_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB51_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v0, v7, v3 @@ -1628,7 +1958,7 @@ define void @flat_atomic_nand_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB41_1 +; GCN2-NEXT: s_cbranch_execnz .LBB51_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] @@ -1638,7 +1968,7 @@ define void @flat_atomic_nand_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB41_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB51_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1653,7 +1983,7 @@ define void @flat_atomic_nand_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB41_1 +; GCN3-NEXT: s_cbranch_execnz .LBB51_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] @@ -1671,7 +2001,7 @@ define i64 @flat_atomic_nand_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: flat_load_dword v5, v[5:6] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB42_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB52_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 v7, v5 @@ -1686,7 +2016,7 @@ define i64 @flat_atomic_nand_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB42_1 +; GCN1-NEXT: s_cbranch_execnz .LBB52_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 @@ -1701,7 +2031,7 @@ define i64 @flat_atomic_nand_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: flat_load_dword v5, v[5:6] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB42_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB52_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 v7, v5 @@ -1716,7 +2046,7 @@ define i64 @flat_atomic_nand_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB42_1 +; GCN2-NEXT: s_cbranch_execnz .LBB52_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 @@ -1728,7 +2058,7 @@ define i64 @flat_atomic_nand_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB42_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB52_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 v7, v5 @@ -1743,7 +2073,7 @@ define i64 @flat_atomic_nand_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB42_1 +; GCN3-NEXT: s_cbranch_execnz .LBB52_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 @@ -1764,7 +2094,7 @@ define i64 @flat_atomic_nand_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v1, v[0:1] ; GCN1-NEXT: flat_load_dword v0, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB43_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB53_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 v9, v1 @@ -1779,7 +2109,7 @@ define i64 @flat_atomic_nand_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB43_1 +; GCN1-NEXT: s_cbranch_execnz .LBB53_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] @@ -1794,7 +2124,7 @@ define i64 @flat_atomic_nand_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v1, v[0:1] ; GCN2-NEXT: flat_load_dword v0, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB43_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB53_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 v9, v1 @@ -1809,7 +2139,7 @@ define i64 @flat_atomic_nand_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB43_1 +; GCN2-NEXT: s_cbranch_execnz .LBB53_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] @@ -1819,7 +2149,7 @@ define i64 @flat_atomic_nand_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB43_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB53_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 v7, v5 @@ -1834,7 +2164,7 @@ define i64 @flat_atomic_nand_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB43_1 +; GCN3-NEXT: s_cbranch_execnz .LBB53_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 @@ -1860,7 +2190,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN1-NEXT: v_mov_b32_e32 v4, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v5, s5 -; GCN1-NEXT: .LBB44_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB54_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_and_b32_e32 v0, s7, v3 @@ -1875,7 +2205,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB44_1 +; GCN1-NEXT: s_cbranch_execnz .LBB54_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] @@ -1894,7 +2224,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN2-NEXT: v_mov_b32_e32 v4, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v5, s5 -; GCN2-NEXT: .LBB44_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB54_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v0, s7, v3 @@ -1909,7 +2239,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB44_1 +; GCN2-NEXT: s_cbranch_execnz .LBB54_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] @@ -1923,7 +2253,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN3-NEXT: v_mov_b32_e32 v4, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB44_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB54_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v0, s7, v3 @@ -1938,7 +2268,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB44_1 +; GCN3-NEXT: s_cbranch_execnz .LBB54_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] @@ -1961,7 +2291,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: flat_load_dword v3, v[0:1] ; GCN1-NEXT: flat_load_dword v2, v[4:5] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB45_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB55_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_and_b32_e32 v0, s7, v3 @@ -1976,7 +2306,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB45_1 +; GCN1-NEXT: s_cbranch_execnz .LBB55_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] @@ -1995,7 +2325,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: flat_load_dword v3, v[0:1] ; GCN2-NEXT: flat_load_dword v2, v[4:5] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB45_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB55_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_and_b32_e32 v0, s7, v3 @@ -2010,7 +2340,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB45_1 +; GCN2-NEXT: s_cbranch_execnz .LBB55_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] @@ -2024,7 +2354,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v4, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB45_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB55_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_and_b32_e32 v0, s7, v3 @@ -2039,7 +2369,7 @@ define amdgpu_gfx void @flat_atomic_nand_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB45_1 +; GCN3-NEXT: s_cbranch_execnz .LBB55_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] @@ -2063,7 +2393,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_mov_b32_e32 v2, s4 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: .LBB46_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB56_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 v7, v1 @@ -2078,7 +2408,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; 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 .LBB46_1 +; GCN1-NEXT: s_cbranch_execnz .LBB56_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] @@ -2097,7 +2427,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_mov_b32_e32 v2, s4 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: .LBB46_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB56_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 v7, v1 @@ -2112,7 +2442,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; 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 .LBB46_1 +; GCN2-NEXT: s_cbranch_execnz .LBB56_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] @@ -2126,7 +2456,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_mov_b32_e32 v2, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB46_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB56_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 v7, v1 @@ -2141,7 +2471,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; 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 .LBB46_1 +; GCN3-NEXT: s_cbranch_execnz .LBB56_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] @@ -2164,7 +2494,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN1-NEXT: flat_load_dword v1, v[0:1] ; GCN1-NEXT: flat_load_dword v0, v[2:3] ; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB47_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB57_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 v7, v1 @@ -2179,7 +2509,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; 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 .LBB47_1 +; GCN1-NEXT: s_cbranch_execnz .LBB57_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] @@ -2198,7 +2528,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN2-NEXT: flat_load_dword v1, v[0:1] ; GCN2-NEXT: flat_load_dword v0, v[2:3] ; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB47_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB57_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 v7, v1 @@ -2213,7 +2543,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; 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 .LBB47_1 +; GCN2-NEXT: s_cbranch_execnz .LBB57_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] @@ -2227,7 +2557,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN3-NEXT: v_mov_b32_e32 v2, s4 ; GCN3-NEXT: s_mov_b64 s[34:35], 0 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB47_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB57_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 v7, v1 @@ -2242,7 +2572,7 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; 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 .LBB47_1 +; GCN3-NEXT: s_cbranch_execnz .LBB57_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] @@ -2251,6 +2581,188 @@ define amdgpu_gfx i64 @flat_atomic_nand_i64_ret_offset_scalar(ptr inreg %out, i6 ret i64 %result } +define void @flat_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v7, v[0:1] +; GCN1-NEXT: flat_load_dword v6, v[8:9] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB58_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_and_b32_e32 v0, v7, v3 +; GCN1-NEXT: v_and_b32_e32 v1, v6, v2 +; GCN1-NEXT: v_not_b32_e32 v5, v0 +; GCN1-NEXT: v_not_b32_e32 v4, v1 +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v1 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v6, v0 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB58_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: flat_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v8, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v7, v[0:1] +; GCN2-NEXT: flat_load_dword v6, v[8:9] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB58_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_and_b32_e32 v0, v7, v3 +; GCN2-NEXT: v_and_b32_e32 v1, v6, v2 +; GCN2-NEXT: v_not_b32_e32 v5, v0 +; GCN2-NEXT: v_not_b32_e32 v4, v1 +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN2-NEXT: v_mov_b32_e32 v7, v1 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v6, v0 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB58_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: flat_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB58_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_and_b32_e32 v4, v7, v3 +; GCN3-NEXT: v_and_b32_e32 v8, v6, v2 +; GCN3-NEXT: v_not_b32_e32 v5, v4 +; GCN3-NEXT: v_not_b32_e32 v4, v8 +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN3-NEXT: v_mov_b32_e32 v7, v5 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB58_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] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw nand ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v1, v[0:1] +; GCN1-NEXT: flat_load_dword v0, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB59_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 v9, v1 +; GCN1-NEXT: v_mov_b32_e32 v8, v0 +; GCN1-NEXT: v_and_b32_e32 v0, v9, v3 +; GCN1-NEXT: v_and_b32_e32 v1, v8, v2 +; GCN1-NEXT: v_not_b32_e32 v7, v0 +; GCN1-NEXT: v_not_b32_e32 v6, v1 +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB59_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: flat_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v1, v[0:1] +; GCN2-NEXT: flat_load_dword v0, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB59_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 v9, v1 +; GCN2-NEXT: v_mov_b32_e32 v8, v0 +; GCN2-NEXT: v_and_b32_e32 v0, v9, v3 +; GCN2-NEXT: v_and_b32_e32 v1, v8, v2 +; GCN2-NEXT: v_not_b32_e32 v7, v0 +; GCN2-NEXT: v_not_b32_e32 v6, v1 +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB59_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: flat_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB59_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 v7, v5 +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: v_and_b32_e32 v4, v7, v3 +; GCN3-NEXT: v_and_b32_e32 v8, v6, v2 +; GCN3-NEXT: v_not_b32_e32 v5, v4 +; GCN3-NEXT: v_not_b32_e32 v4, v8 +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; 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 .LBB59_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: v_mov_b32_e32 v1, v5 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw nand ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw or ; --------------------------------------------------------------------- @@ -2547,23 +3059,89 @@ define amdgpu_gfx i64 @flat_atomic_or_i64_ret_offset_scalar(ptr inreg %out, i64 ret i64 %result } -; --------------------------------------------------------------------- -; atomicrmw xor -; --------------------------------------------------------------------- - -define void @flat_atomic_xor_i64_noret(ptr %ptr, i64 %in) { -; GCN1-LABEL: flat_atomic_xor_i64_noret: +define void @flat_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_or_x2 v[0:1], v[2:3] ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol ; GCN1-NEXT: s_setpc_b64 s[30:31] ; -; GCN2-LABEL: flat_atomic_xor_i64_noret: +; GCN2-LABEL: flat_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN2: ; %bb.0: ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_or_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_or_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw or ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_or_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_or_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_or_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw or ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw xor +; --------------------------------------------------------------------- + +define void @flat_atomic_xor_i64_noret(ptr %ptr, i64 %in) { +; GCN1-LABEL: flat_atomic_xor_i64_noret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xor_i64_noret: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol ; GCN2-NEXT: s_setpc_b64 s[30:31] @@ -2843,6 +3421,72 @@ define amdgpu_gfx i64 @flat_atomic_xor_i64_ret_offset_scalar(ptr inreg %out, i64 ret i64 %result } +define void @flat_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw xor ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_xor_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_xor_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_xor_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw xor ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw max ; --------------------------------------------------------------------- @@ -2856,7 +3500,7 @@ define void @flat_atomic_max_i64_noret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v6, v[0:1] ; GCN1-NEXT: flat_load_dword v7, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB64_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB80_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -2870,7 +3514,7 @@ define void @flat_atomic_max_i64_noret(ptr %ptr, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v4 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB64_1 +; GCN1-NEXT: s_cbranch_execnz .LBB80_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] @@ -2883,7 +3527,7 @@ define void @flat_atomic_max_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v6, v[0:1] ; GCN2-NEXT: flat_load_dword v7, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB64_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB80_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -2897,7 +3541,7 @@ define void @flat_atomic_max_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v4 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB64_1 +; GCN2-NEXT: s_cbranch_execnz .LBB80_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] @@ -2907,7 +3551,7 @@ define void @flat_atomic_max_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB64_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB80_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -2921,7 +3565,7 @@ define void @flat_atomic_max_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB64_1 +; GCN3-NEXT: s_cbranch_execnz .LBB80_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] @@ -2940,7 +3584,7 @@ define void @flat_atomic_max_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v7, v[0:1] ; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB65_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB81_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -2954,7 +3598,7 @@ define void @flat_atomic_max_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB65_1 +; GCN1-NEXT: s_cbranch_execnz .LBB81_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] @@ -2969,7 +3613,7 @@ define void @flat_atomic_max_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v7, v[0:1] ; GCN2-NEXT: flat_load_dword v6, v[8:9] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB65_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB81_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -2983,7 +3627,7 @@ define void @flat_atomic_max_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB65_1 +; GCN2-NEXT: s_cbranch_execnz .LBB81_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] @@ -2993,7 +3637,7 @@ define void @flat_atomic_max_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB65_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB81_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3007,7 +3651,7 @@ define void @flat_atomic_max_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB65_1 +; GCN3-NEXT: s_cbranch_execnz .LBB81_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] @@ -3025,7 +3669,7 @@ define i64 @flat_atomic_max_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: flat_load_dword v5, v[5:6] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB66_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB82_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 v7, v5 @@ -3039,7 +3683,7 @@ define i64 @flat_atomic_max_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB66_1 +; GCN1-NEXT: s_cbranch_execnz .LBB82_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 @@ -3054,7 +3698,7 @@ define i64 @flat_atomic_max_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: flat_load_dword v5, v[5:6] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB66_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB82_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 v7, v5 @@ -3068,7 +3712,7 @@ define i64 @flat_atomic_max_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB66_1 +; GCN2-NEXT: s_cbranch_execnz .LBB82_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 @@ -3080,7 +3724,7 @@ define i64 @flat_atomic_max_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB66_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB82_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 v7, v5 @@ -3094,7 +3738,7 @@ define i64 @flat_atomic_max_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB66_1 +; GCN3-NEXT: s_cbranch_execnz .LBB82_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 @@ -3115,7 +3759,7 @@ define i64 @flat_atomic_max_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v1, v[0:1] ; GCN1-NEXT: flat_load_dword v0, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB67_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB83_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 v9, v1 @@ -3129,7 +3773,7 @@ define i64 @flat_atomic_max_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB67_1 +; GCN1-NEXT: s_cbranch_execnz .LBB83_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] @@ -3144,7 +3788,7 @@ define i64 @flat_atomic_max_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v1, v[0:1] ; GCN2-NEXT: flat_load_dword v0, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB67_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB83_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 v9, v1 @@ -3158,7 +3802,7 @@ define i64 @flat_atomic_max_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB67_1 +; GCN2-NEXT: s_cbranch_execnz .LBB83_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] @@ -3168,7 +3812,7 @@ define i64 @flat_atomic_max_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB67_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB83_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 v7, v5 @@ -3182,7 +3826,7 @@ define i64 @flat_atomic_max_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB67_1 +; GCN3-NEXT: s_cbranch_execnz .LBB83_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 @@ -3210,7 +3854,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 ; GCN1-NEXT: v_mov_b32_e32 v5, s5 -; GCN1-NEXT: .LBB68_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB84_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3224,7 +3868,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB68_1 +; GCN1-NEXT: s_cbranch_execnz .LBB84_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] @@ -3245,7 +3889,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 ; GCN2-NEXT: v_mov_b32_e32 v5, s5 -; GCN2-NEXT: .LBB68_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB84_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3259,7 +3903,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB68_1 +; GCN2-NEXT: s_cbranch_execnz .LBB84_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] @@ -3275,7 +3919,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB68_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB84_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3289,7 +3933,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB68_1 +; GCN3-NEXT: s_cbranch_execnz .LBB84_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] @@ -3314,7 +3958,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 -; GCN1-NEXT: .LBB69_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB85_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3328,7 +3972,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB69_1 +; GCN1-NEXT: s_cbranch_execnz .LBB85_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] @@ -3349,7 +3993,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 -; GCN2-NEXT: .LBB69_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB85_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3363,7 +4007,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB69_1 +; GCN2-NEXT: s_cbranch_execnz .LBB85_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] @@ -3379,7 +4023,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB69_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB85_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3393,7 +4037,7 @@ define amdgpu_gfx void @flat_atomic_max_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB69_1 +; GCN3-NEXT: s_cbranch_execnz .LBB85_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] @@ -3419,7 +4063,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 ; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: .LBB70_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB86_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 v9, v1 @@ -3433,7 +4077,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB70_1 +; GCN1-NEXT: s_cbranch_execnz .LBB86_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] @@ -3454,7 +4098,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 ; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: .LBB70_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB86_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 v9, v1 @@ -3468,7 +4112,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB70_1 +; GCN2-NEXT: s_cbranch_execnz .LBB86_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] @@ -3484,7 +4128,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB70_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB86_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 v9, v1 @@ -3498,7 +4142,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB70_1 +; GCN3-NEXT: s_cbranch_execnz .LBB86_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] @@ -3523,7 +4167,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 -; GCN1-NEXT: .LBB71_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB87_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 v9, v1 @@ -3537,7 +4181,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB71_1 +; GCN1-NEXT: s_cbranch_execnz .LBB87_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] @@ -3558,7 +4202,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 -; GCN2-NEXT: .LBB71_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB87_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 v9, v1 @@ -3572,7 +4216,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB71_1 +; GCN2-NEXT: s_cbranch_execnz .LBB87_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] @@ -3588,7 +4232,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB71_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB87_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 v9, v1 @@ -3602,7 +4246,7 @@ define amdgpu_gfx i64 @flat_atomic_max_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB71_1 +; GCN3-NEXT: s_cbranch_execnz .LBB87_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] @@ -3628,7 +4272,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s3 ; GCN1-NEXT: v_mov_b32_e32 v7, s2 -; GCN1-NEXT: .LBB72_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB88_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] @@ -3642,7 +4286,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB72_1 +; GCN1-NEXT: s_cbranch_execnz .LBB88_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -3662,7 +4306,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s3 ; GCN2-NEXT: v_mov_b32_e32 v7, s2 -; GCN2-NEXT: .LBB72_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB88_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] @@ -3676,7 +4320,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB72_1 +; GCN2-NEXT: s_cbranch_execnz .LBB88_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -3694,7 +4338,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 -; GCN3-NEXT: .LBB72_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB88_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3708,7 +4352,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB72_1 +; GCN3-NEXT: s_cbranch_execnz .LBB88_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -3734,7 +4378,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s5 ; GCN1-NEXT: v_mov_b32_e32 v5, s4 -; GCN1-NEXT: .LBB73_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB89_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 v9, v3 @@ -3748,7 +4392,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB73_1 +; GCN1-NEXT: s_cbranch_execnz .LBB89_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -3771,7 +4415,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s5 ; GCN2-NEXT: v_mov_b32_e32 v5, s4 -; GCN2-NEXT: .LBB73_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB89_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 v9, v3 @@ -3785,7 +4429,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB73_1 +; GCN2-NEXT: s_cbranch_execnz .LBB89_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -3806,7 +4450,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v4, s5 ; GCN3-NEXT: v_mov_b32_e32 v5, s4 -; GCN3-NEXT: .LBB73_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB89_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 v9, v3 @@ -3820,7 +4464,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB73_1 +; GCN3-NEXT: s_cbranch_execnz .LBB89_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s2 @@ -3850,7 +4494,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr %out, i64 %in, i64 %index) ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s3 ; GCN1-NEXT: v_mov_b32_e32 v7, s2 -; GCN1-NEXT: .LBB74_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB90_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] @@ -3864,7 +4508,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr %out, i64 %in, i64 %index) ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB74_1 +; GCN1-NEXT: s_cbranch_execnz .LBB90_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -3882,7 +4526,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr %out, i64 %in, i64 %index) ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s3 ; GCN2-NEXT: v_mov_b32_e32 v7, s2 -; GCN2-NEXT: .LBB74_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB90_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] @@ -3896,7 +4540,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr %out, i64 %in, i64 %index) ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB74_1 +; GCN2-NEXT: s_cbranch_execnz .LBB90_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -3914,7 +4558,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr %out, i64 %in, i64 %index) ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 -; GCN3-NEXT: .LBB74_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB90_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3928,7 +4572,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr %out, i64 %in, i64 %index) ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB74_1 +; GCN3-NEXT: s_cbranch_execnz .LBB90_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -3951,7 +4595,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s5 ; GCN1-NEXT: v_mov_b32_e32 v5, s4 -; GCN1-NEXT: .LBB75_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB91_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 v9, v3 @@ -3965,7 +4609,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB75_1 +; GCN1-NEXT: s_cbranch_execnz .LBB91_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -3986,7 +4630,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s5 ; GCN2-NEXT: v_mov_b32_e32 v5, s4 -; GCN2-NEXT: .LBB75_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB91_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 v9, v3 @@ -4000,7 +4644,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB75_1 +; GCN2-NEXT: s_cbranch_execnz .LBB91_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -4021,7 +4665,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v4, s5 ; GCN3-NEXT: v_mov_b32_e32 v5, s4 -; GCN3-NEXT: .LBB75_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB91_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 v9, v3 @@ -4035,7 +4679,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB75_1 +; GCN3-NEXT: s_cbranch_execnz .LBB91_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s2 @@ -4049,77 +4693,77 @@ entry: ret void } -; --------------------------------------------------------------------- -; atomicrmw umax -; --------------------------------------------------------------------- - -define void @flat_atomic_umax_i64_noret(ptr %ptr, i64 %in) { -; GCN1-LABEL: flat_atomic_umax_i64_noret: +define void @flat_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_i32_e32 v4, vcc, 4, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: flat_load_dword v6, v[0:1] -; GCN1-NEXT: flat_load_dword v7, v[4:5] +; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v7, v[0:1] +; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB76_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB92_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN1-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] ; GCN1-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; GCN1-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc -; GCN1-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] -; GCN1-NEXT: v_mov_b32_e32 v7, v5 +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v1 ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v6, v4 +; GCN1-NEXT: v_mov_b32_e32 v6, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB76_1 +; GCN1-NEXT: s_cbranch_execnz .LBB92_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: flat_atomic_umax_i64_noret: +; GCN2-LABEL: flat_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN2: ; %bb.0: ; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v4, vcc, 4, v0 -; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN2-NEXT: flat_load_dword v6, v[0:1] -; GCN2-NEXT: flat_load_dword v7, v[4:5] +; GCN2-NEXT: v_add_u32_e32 v8, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v7, v[0:1] +; GCN2-NEXT: flat_load_dword v6, v[8:9] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB76_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB92_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN2-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] ; GCN2-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; GCN2-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc -; GCN2-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] -; GCN2-NEXT: v_mov_b32_e32 v7, v5 +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN2-NEXT: v_mov_b32_e32 v7, v1 ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v6, v4 +; GCN2-NEXT: v_mov_b32_e32 v6, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB76_1 +; GCN2-NEXT: s_cbranch_execnz .LBB92_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: flat_atomic_umax_i64_noret: +; GCN3-LABEL: flat_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN3: ; %bb.0: ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB76_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB92_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] ; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc -; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: buffer_wbinvl1_vol ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] @@ -4127,26 +4771,202 @@ define void @flat_atomic_umax_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB76_1 +; GCN3-NEXT: s_cbranch_execnz .LBB92_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] - %tmp0 = atomicrmw umax ptr %ptr, i64 %in seq_cst + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw max ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret void } -define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { -; GCN1-LABEL: flat_atomic_umax_i64_noret_offset: +define i64 @flat_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 -; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v1, v[0:1] +; GCN1-NEXT: flat_load_dword v0, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB93_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 v9, v1 +; GCN1-NEXT: v_mov_b32_e32 v8, v0 +; GCN1-NEXT: v_cmp_gt_i64_e32 vcc, v[8:9], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB93_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: flat_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v1, v[0:1] +; GCN2-NEXT: flat_load_dword v0, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB93_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 v9, v1 +; GCN2-NEXT: v_mov_b32_e32 v8, v0 +; GCN2-NEXT: v_cmp_gt_i64_e32 vcc, v[8:9], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB93_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: flat_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB93_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 v7, v5 +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; 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 .LBB93_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: v_mov_b32_e32 v1, v5 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw max ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw umax +; --------------------------------------------------------------------- + +define void @flat_atomic_umax_i64_noret(ptr %ptr, i64 %in) { +; GCN1-LABEL: flat_atomic_umax_i64_noret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 4, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v6, v[0:1] +; GCN1-NEXT: flat_load_dword v7, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v5 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v6, v4 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB94_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: flat_atomic_umax_i64_noret: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 4, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v6, v[0:1] +; GCN2-NEXT: flat_load_dword v7, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN2-NEXT: v_mov_b32_e32 v7, v5 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v6, v4 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB94_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: flat_atomic_umax_i64_noret: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN3-NEXT: v_mov_b32_e32 v7, v5 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB94_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] + %tmp0 = atomicrmw umax ptr %ptr, i64 %in seq_cst + ret void +} + +define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_umax_i64_noret_offset: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc ; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 ; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GCN1-NEXT: flat_load_dword v7, v[0:1] ; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB77_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB95_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] @@ -4160,7 +4980,7 @@ define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB77_1 +; GCN1-NEXT: s_cbranch_execnz .LBB95_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] @@ -4175,7 +4995,7 @@ define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v7, v[0:1] ; GCN2-NEXT: flat_load_dword v6, v[8:9] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB77_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB95_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] @@ -4189,7 +5009,7 @@ define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB77_1 +; GCN2-NEXT: s_cbranch_execnz .LBB95_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] @@ -4199,7 +5019,7 @@ define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB77_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB95_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] @@ -4213,7 +5033,7 @@ define void @flat_atomic_umax_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB77_1 +; GCN3-NEXT: s_cbranch_execnz .LBB95_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] @@ -4231,7 +5051,7 @@ define i64 @flat_atomic_umax_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: flat_load_dword v5, v[5:6] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB78_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB96_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 v7, v5 @@ -4245,7 +5065,7 @@ define i64 @flat_atomic_umax_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB78_1 +; GCN1-NEXT: s_cbranch_execnz .LBB96_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 @@ -4260,7 +5080,7 @@ define i64 @flat_atomic_umax_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: flat_load_dword v5, v[5:6] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB78_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB96_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 v7, v5 @@ -4274,7 +5094,7 @@ define i64 @flat_atomic_umax_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB78_1 +; GCN2-NEXT: s_cbranch_execnz .LBB96_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 @@ -4286,7 +5106,7 @@ define i64 @flat_atomic_umax_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB78_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB96_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 v7, v5 @@ -4300,7 +5120,7 @@ define i64 @flat_atomic_umax_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB78_1 +; GCN3-NEXT: s_cbranch_execnz .LBB96_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 @@ -4321,7 +5141,7 @@ define i64 @flat_atomic_umax_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v1, v[0:1] ; GCN1-NEXT: flat_load_dword v0, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB79_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB97_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 v9, v1 @@ -4335,7 +5155,7 @@ define i64 @flat_atomic_umax_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB79_1 +; GCN1-NEXT: s_cbranch_execnz .LBB97_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] @@ -4350,7 +5170,7 @@ define i64 @flat_atomic_umax_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v1, v[0:1] ; GCN2-NEXT: flat_load_dword v0, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB79_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB97_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 v9, v1 @@ -4364,7 +5184,7 @@ define i64 @flat_atomic_umax_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB79_1 +; GCN2-NEXT: s_cbranch_execnz .LBB97_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] @@ -4374,7 +5194,7 @@ define i64 @flat_atomic_umax_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB79_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB97_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 v7, v5 @@ -4388,7 +5208,7 @@ define i64 @flat_atomic_umax_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB79_1 +; GCN3-NEXT: s_cbranch_execnz .LBB97_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 @@ -4416,7 +5236,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 ; GCN1-NEXT: v_mov_b32_e32 v5, s5 -; GCN1-NEXT: .LBB80_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB98_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4430,7 +5250,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB80_1 +; GCN1-NEXT: s_cbranch_execnz .LBB98_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] @@ -4451,7 +5271,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 ; GCN2-NEXT: v_mov_b32_e32 v5, s5 -; GCN2-NEXT: .LBB80_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB98_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4465,7 +5285,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB80_1 +; GCN2-NEXT: s_cbranch_execnz .LBB98_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] @@ -4481,7 +5301,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB80_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB98_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4495,7 +5315,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB80_1 +; GCN3-NEXT: s_cbranch_execnz .LBB98_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] @@ -4520,7 +5340,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 -; GCN1-NEXT: .LBB81_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB99_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4534,7 +5354,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB81_1 +; GCN1-NEXT: s_cbranch_execnz .LBB99_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] @@ -4555,7 +5375,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 -; GCN2-NEXT: .LBB81_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB99_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4569,7 +5389,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB81_1 +; GCN2-NEXT: s_cbranch_execnz .LBB99_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] @@ -4585,7 +5405,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB81_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB99_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4599,7 +5419,7 @@ define amdgpu_gfx void @flat_atomic_umax_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB81_1 +; GCN3-NEXT: s_cbranch_execnz .LBB99_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] @@ -4625,7 +5445,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 ; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: .LBB82_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB100_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 v9, v1 @@ -4639,7 +5459,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB82_1 +; GCN1-NEXT: s_cbranch_execnz .LBB100_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] @@ -4660,7 +5480,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 ; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: .LBB82_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB100_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 v9, v1 @@ -4674,7 +5494,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB82_1 +; GCN2-NEXT: s_cbranch_execnz .LBB100_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] @@ -4690,7 +5510,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB82_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB100_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 v9, v1 @@ -4704,7 +5524,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB82_1 +; GCN3-NEXT: s_cbranch_execnz .LBB100_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] @@ -4729,7 +5549,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 -; GCN1-NEXT: .LBB83_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB101_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 v9, v1 @@ -4743,7 +5563,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB83_1 +; GCN1-NEXT: s_cbranch_execnz .LBB101_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] @@ -4764,7 +5584,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 -; GCN2-NEXT: .LBB83_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB101_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 v9, v1 @@ -4778,7 +5598,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB83_1 +; GCN2-NEXT: s_cbranch_execnz .LBB101_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] @@ -4794,7 +5614,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB83_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB101_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 v9, v1 @@ -4808,7 +5628,7 @@ define amdgpu_gfx i64 @flat_atomic_umax_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB83_1 +; GCN3-NEXT: s_cbranch_execnz .LBB101_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] @@ -4834,7 +5654,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr %out, i64 %in, i64 ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s3 ; GCN1-NEXT: v_mov_b32_e32 v7, s2 -; GCN1-NEXT: .LBB84_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB102_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_lt_u64_e32 vcc, s[2:3], v[2:3] @@ -4848,7 +5668,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr %out, i64 %in, i64 ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB84_1 +; GCN1-NEXT: s_cbranch_execnz .LBB102_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -4868,7 +5688,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr %out, i64 %in, i64 ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s3 ; GCN2-NEXT: v_mov_b32_e32 v7, s2 -; GCN2-NEXT: .LBB84_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB102_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_lt_u64_e32 vcc, s[2:3], v[2:3] @@ -4882,7 +5702,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr %out, i64 %in, i64 ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB84_1 +; GCN2-NEXT: s_cbranch_execnz .LBB102_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -4900,7 +5720,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr %out, i64 %in, i64 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 -; GCN3-NEXT: .LBB84_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB102_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -4914,7 +5734,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr %out, i64 %in, i64 ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB84_1 +; GCN3-NEXT: s_cbranch_execnz .LBB102_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -4940,7 +5760,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr %out, ptr %out2 ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s5 ; GCN1-NEXT: v_mov_b32_e32 v5, s4 -; GCN1-NEXT: .LBB85_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB103_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 v9, v3 @@ -4954,7 +5774,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr %out, ptr %out2 ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB85_1 +; GCN1-NEXT: s_cbranch_execnz .LBB103_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -4977,7 +5797,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr %out, ptr %out2 ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s5 ; GCN2-NEXT: v_mov_b32_e32 v5, s4 -; GCN2-NEXT: .LBB85_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB103_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 v9, v3 @@ -4991,7 +5811,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr %out, ptr %out2 ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB85_1 +; GCN2-NEXT: s_cbranch_execnz .LBB103_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -5012,7 +5832,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr %out, ptr %out2 ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v4, s5 ; GCN3-NEXT: v_mov_b32_e32 v5, s4 -; GCN3-NEXT: .LBB85_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB103_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 v9, v3 @@ -5026,7 +5846,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr %out, ptr %out2 ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB85_1 +; GCN3-NEXT: s_cbranch_execnz .LBB103_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s2 @@ -5055,7 +5875,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr %out, ptr %out2, i64 % ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s5 ; GCN1-NEXT: v_mov_b32_e32 v5, s4 -; GCN1-NEXT: .LBB86_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB104_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 v9, v3 @@ -5069,7 +5889,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr %out, ptr %out2, i64 % ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB86_1 +; GCN1-NEXT: s_cbranch_execnz .LBB104_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -5090,7 +5910,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr %out, ptr %out2, i64 % ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s5 ; GCN2-NEXT: v_mov_b32_e32 v5, s4 -; GCN2-NEXT: .LBB86_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB104_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 v9, v3 @@ -5104,7 +5924,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr %out, ptr %out2, i64 % ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB86_1 +; GCN2-NEXT: s_cbranch_execnz .LBB104_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -5125,7 +5945,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr %out, ptr %out2, i64 % ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v4, s5 ; GCN3-NEXT: v_mov_b32_e32 v5, s4 -; GCN3-NEXT: .LBB86_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB104_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 v9, v3 @@ -5139,7 +5959,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr %out, ptr %out2, i64 % ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB86_1 +; GCN3-NEXT: s_cbranch_execnz .LBB104_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s2 @@ -5153,6 +5973,182 @@ entry: ret void } +define void @flat_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v7, v[0:1] +; GCN1-NEXT: flat_load_dword v6, v[8:9] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v1 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v6, v0 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB105_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: flat_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v8, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v7, v[0:1] +; GCN2-NEXT: flat_load_dword v6, v[8:9] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN2-NEXT: v_mov_b32_e32 v7, v1 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v6, v0 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB105_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: flat_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN3-NEXT: v_mov_b32_e32 v7, v5 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB105_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] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw umax ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v1, v[0:1] +; GCN1-NEXT: flat_load_dword v0, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB106_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 v9, v1 +; GCN1-NEXT: v_mov_b32_e32 v8, v0 +; GCN1-NEXT: v_cmp_gt_u64_e32 vcc, v[8:9], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB106_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: flat_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v1, v[0:1] +; GCN2-NEXT: flat_load_dword v0, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB106_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 v9, v1 +; GCN2-NEXT: v_mov_b32_e32 v8, v0 +; GCN2-NEXT: v_cmp_gt_u64_e32 vcc, v[8:9], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB106_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: flat_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB106_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 v7, v5 +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; 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 .LBB106_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: v_mov_b32_e32 v1, v5 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw umax ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw umin ; --------------------------------------------------------------------- @@ -5166,7 +6162,7 @@ define void @flat_atomic_umin_i64_noret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v6, v[0:1] ; GCN1-NEXT: flat_load_dword v7, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB87_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB107_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5180,7 +6176,7 @@ define void @flat_atomic_umin_i64_noret(ptr %ptr, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v4 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB87_1 +; GCN1-NEXT: s_cbranch_execnz .LBB107_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] @@ -5193,7 +6189,7 @@ define void @flat_atomic_umin_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v6, v[0:1] ; GCN2-NEXT: flat_load_dword v7, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB87_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB107_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5207,7 +6203,7 @@ define void @flat_atomic_umin_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v4 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB87_1 +; GCN2-NEXT: s_cbranch_execnz .LBB107_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] @@ -5217,7 +6213,7 @@ define void @flat_atomic_umin_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB87_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB107_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5231,7 +6227,7 @@ define void @flat_atomic_umin_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB87_1 +; GCN3-NEXT: s_cbranch_execnz .LBB107_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] @@ -5250,7 +6246,7 @@ define void @flat_atomic_umin_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v7, v[0:1] ; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB88_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB108_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5264,7 +6260,7 @@ define void @flat_atomic_umin_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB88_1 +; GCN1-NEXT: s_cbranch_execnz .LBB108_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] @@ -5279,7 +6275,7 @@ define void @flat_atomic_umin_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v7, v[0:1] ; GCN2-NEXT: flat_load_dword v6, v[8:9] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB88_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB108_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5293,7 +6289,7 @@ define void @flat_atomic_umin_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB88_1 +; GCN2-NEXT: s_cbranch_execnz .LBB108_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] @@ -5303,7 +6299,7 @@ define void @flat_atomic_umin_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB88_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB108_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5317,7 +6313,7 @@ define void @flat_atomic_umin_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB88_1 +; GCN3-NEXT: s_cbranch_execnz .LBB108_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] @@ -5335,7 +6331,7 @@ define i64 @flat_atomic_umin_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: flat_load_dword v5, v[5:6] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB89_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB109_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 v7, v5 @@ -5349,7 +6345,7 @@ define i64 @flat_atomic_umin_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB89_1 +; GCN1-NEXT: s_cbranch_execnz .LBB109_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 @@ -5364,7 +6360,7 @@ define i64 @flat_atomic_umin_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: flat_load_dword v5, v[5:6] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB89_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB109_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 v7, v5 @@ -5378,7 +6374,7 @@ define i64 @flat_atomic_umin_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB89_1 +; GCN2-NEXT: s_cbranch_execnz .LBB109_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 @@ -5390,7 +6386,7 @@ define i64 @flat_atomic_umin_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB89_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB109_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 v7, v5 @@ -5404,7 +6400,7 @@ define i64 @flat_atomic_umin_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB89_1 +; GCN3-NEXT: s_cbranch_execnz .LBB109_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 @@ -5425,7 +6421,7 @@ define i64 @flat_atomic_umin_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v1, v[0:1] ; GCN1-NEXT: flat_load_dword v0, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB90_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB110_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 v9, v1 @@ -5439,7 +6435,7 @@ define i64 @flat_atomic_umin_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB90_1 +; GCN1-NEXT: s_cbranch_execnz .LBB110_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] @@ -5454,7 +6450,7 @@ define i64 @flat_atomic_umin_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v1, v[0:1] ; GCN2-NEXT: flat_load_dword v0, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB90_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB110_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 v9, v1 @@ -5468,7 +6464,7 @@ define i64 @flat_atomic_umin_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB90_1 +; GCN2-NEXT: s_cbranch_execnz .LBB110_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] @@ -5478,7 +6474,7 @@ define i64 @flat_atomic_umin_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB90_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB110_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 v7, v5 @@ -5492,7 +6488,7 @@ define i64 @flat_atomic_umin_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB90_1 +; GCN3-NEXT: s_cbranch_execnz .LBB110_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 @@ -5520,7 +6516,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 ; GCN1-NEXT: v_mov_b32_e32 v5, s5 -; GCN1-NEXT: .LBB91_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB111_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -5534,7 +6530,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB91_1 +; GCN1-NEXT: s_cbranch_execnz .LBB111_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] @@ -5555,7 +6551,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 ; GCN2-NEXT: v_mov_b32_e32 v5, s5 -; GCN2-NEXT: .LBB91_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB111_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -5569,7 +6565,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB91_1 +; GCN2-NEXT: s_cbranch_execnz .LBB111_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] @@ -5585,7 +6581,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB91_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB111_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -5599,7 +6595,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_scalar(ptr inreg %ptr, i64 in ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB91_1 +; GCN3-NEXT: s_cbranch_execnz .LBB111_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] @@ -5624,7 +6620,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 -; GCN1-NEXT: .LBB92_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB112_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -5638,7 +6634,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB92_1 +; GCN1-NEXT: s_cbranch_execnz .LBB112_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] @@ -5659,7 +6655,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 -; GCN2-NEXT: .LBB92_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB112_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -5673,7 +6669,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB92_1 +; GCN2-NEXT: s_cbranch_execnz .LBB112_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] @@ -5689,7 +6685,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB92_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB112_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -5703,7 +6699,7 @@ define amdgpu_gfx void @flat_atomic_umin_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB92_1 +; GCN3-NEXT: s_cbranch_execnz .LBB112_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] @@ -5729,7 +6725,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 ; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: .LBB93_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB113_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 v9, v1 @@ -5743,7 +6739,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB93_1 +; GCN1-NEXT: s_cbranch_execnz .LBB113_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] @@ -5764,7 +6760,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 ; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: .LBB93_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB113_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 v9, v1 @@ -5778,7 +6774,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB93_1 +; GCN2-NEXT: s_cbranch_execnz .LBB113_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] @@ -5794,7 +6790,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB93_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB113_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 v9, v1 @@ -5808,7 +6804,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB93_1 +; GCN3-NEXT: s_cbranch_execnz .LBB113_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] @@ -5833,7 +6829,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 -; GCN1-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB114_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 v9, v1 @@ -5847,7 +6843,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB94_1 +; GCN1-NEXT: s_cbranch_execnz .LBB114_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] @@ -5868,7 +6864,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 -; GCN2-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB114_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 v9, v1 @@ -5882,7 +6878,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB94_1 +; GCN2-NEXT: s_cbranch_execnz .LBB114_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] @@ -5898,7 +6894,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB94_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB114_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 v9, v1 @@ -5912,7 +6908,7 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB94_1 +; GCN3-NEXT: s_cbranch_execnz .LBB114_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] @@ -5921,34 +6917,210 @@ define amdgpu_gfx i64 @flat_atomic_umin_i64_ret_offset_scalar(ptr inreg %out, i6 ret i64 %result } -; --------------------------------------------------------------------- -; atomicrmw min -; --------------------------------------------------------------------- - -define void @flat_atomic_min_i64_noret(ptr %ptr, i64 %in) { -; GCN1-LABEL: flat_atomic_min_i64_noret: +define void @flat_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access: ; GCN1: ; %bb.0: ; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_i32_e32 v4, vcc, 4, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: flat_load_dword v6, v[0:1] -; GCN1-NEXT: flat_load_dword v7, v[4:5] +; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v7, v[0:1] +; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB115_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GCN1-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] ; GCN1-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; GCN1-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc -; GCN1-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v1 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v6, v0 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB115_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: flat_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v8, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v7, v[0:1] +; GCN2-NEXT: flat_load_dword v6, v[8:9] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB115_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN2-NEXT: v_mov_b32_e32 v7, v1 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v6, v0 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB115_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: flat_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB115_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN3-NEXT: v_mov_b32_e32 v7, v5 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB115_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] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw umin ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v1, v[0:1] +; GCN1-NEXT: flat_load_dword v0, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB116_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 v9, v1 +; GCN1-NEXT: v_mov_b32_e32 v8, v0 +; GCN1-NEXT: v_cmp_le_u64_e32 vcc, v[8:9], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB116_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: flat_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v1, v[0:1] +; GCN2-NEXT: flat_load_dword v0, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB116_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 v9, v1 +; GCN2-NEXT: v_mov_b32_e32 v8, v0 +; GCN2-NEXT: v_cmp_le_u64_e32 vcc, v[8:9], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB116_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: flat_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB116_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 v7, v5 +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; 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 .LBB116_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: v_mov_b32_e32 v1, v5 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw umin ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw min +; --------------------------------------------------------------------- + +define void @flat_atomic_min_i64_noret(ptr %ptr, i64 %in) { +; GCN1-LABEL: flat_atomic_min_i64_noret: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 4, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v6, v[0:1] +; GCN1-NEXT: flat_load_dword v7, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB117_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GCN1-NEXT: v_mov_b32_e32 v7, v5 ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v4 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB95_1 +; GCN1-NEXT: s_cbranch_execnz .LBB117_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] @@ -5961,7 +7133,7 @@ define void @flat_atomic_min_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v6, v[0:1] ; GCN2-NEXT: flat_load_dword v7, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB117_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -5975,7 +7147,7 @@ define void @flat_atomic_min_i64_noret(ptr %ptr, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v4 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB95_1 +; GCN2-NEXT: s_cbranch_execnz .LBB117_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] @@ -5985,7 +7157,7 @@ define void @flat_atomic_min_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB95_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB117_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -5999,7 +7171,7 @@ define void @flat_atomic_min_i64_noret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB95_1 +; GCN3-NEXT: s_cbranch_execnz .LBB117_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] @@ -6018,7 +7190,7 @@ define void @flat_atomic_min_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v7, v[0:1] ; GCN1-NEXT: flat_load_dword v6, v[8:9] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB96_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB118_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6032,7 +7204,7 @@ define void @flat_atomic_min_i64_noret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v6, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB96_1 +; GCN1-NEXT: s_cbranch_execnz .LBB118_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] @@ -6047,7 +7219,7 @@ define void @flat_atomic_min_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v7, v[0:1] ; GCN2-NEXT: flat_load_dword v6, v[8:9] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB96_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB118_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6061,7 +7233,7 @@ define void @flat_atomic_min_i64_noret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v6, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB96_1 +; GCN2-NEXT: s_cbranch_execnz .LBB118_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] @@ -6071,7 +7243,7 @@ define void @flat_atomic_min_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB96_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB118_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6085,7 +7257,7 @@ define void @flat_atomic_min_i64_noret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v6, v4 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB96_1 +; GCN3-NEXT: s_cbranch_execnz .LBB118_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] @@ -6103,7 +7275,7 @@ define i64 @flat_atomic_min_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: flat_load_dword v4, v[0:1] ; GCN1-NEXT: flat_load_dword v5, v[5:6] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB97_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB119_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 v7, v5 @@ -6117,7 +7289,7 @@ define i64 @flat_atomic_min_i64_ret(ptr %ptr, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB97_1 +; GCN1-NEXT: s_cbranch_execnz .LBB119_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 @@ -6132,7 +7304,7 @@ define i64 @flat_atomic_min_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: flat_load_dword v4, v[0:1] ; GCN2-NEXT: flat_load_dword v5, v[5:6] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB97_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB119_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 v7, v5 @@ -6146,7 +7318,7 @@ define i64 @flat_atomic_min_i64_ret(ptr %ptr, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB97_1 +; GCN2-NEXT: s_cbranch_execnz .LBB119_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 @@ -6158,7 +7330,7 @@ define i64 @flat_atomic_min_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB97_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB119_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 v7, v5 @@ -6172,7 +7344,7 @@ define i64 @flat_atomic_min_i64_ret(ptr %ptr, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB97_1 +; GCN3-NEXT: s_cbranch_execnz .LBB119_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 @@ -6193,7 +7365,7 @@ define i64 @flat_atomic_min_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: flat_load_dword v1, v[0:1] ; GCN1-NEXT: flat_load_dword v0, v[4:5] ; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB98_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB120_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 v9, v1 @@ -6207,7 +7379,7 @@ define i64 @flat_atomic_min_i64_ret_offset(ptr %out, i64 %in) { ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB98_1 +; GCN1-NEXT: s_cbranch_execnz .LBB120_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] @@ -6222,7 +7394,7 @@ define i64 @flat_atomic_min_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: flat_load_dword v1, v[0:1] ; GCN2-NEXT: flat_load_dword v0, v[4:5] ; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB98_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB120_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 v9, v1 @@ -6236,7 +7408,7 @@ define i64 @flat_atomic_min_i64_ret_offset(ptr %out, i64 %in) { ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB98_1 +; GCN2-NEXT: s_cbranch_execnz .LBB120_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] @@ -6246,7 +7418,7 @@ define i64 @flat_atomic_min_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 ; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB98_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB120_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 v7, v5 @@ -6260,7 +7432,7 @@ define i64 @flat_atomic_min_i64_ret_offset(ptr %out, i64 %in) { ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; 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 .LBB98_1 +; GCN3-NEXT: s_cbranch_execnz .LBB120_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 @@ -6288,7 +7460,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 ; GCN1-NEXT: v_mov_b32_e32 v5, s5 -; GCN1-NEXT: .LBB99_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB121_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6302,7 +7474,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB99_1 +; GCN1-NEXT: s_cbranch_execnz .LBB121_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] @@ -6323,7 +7495,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 ; GCN2-NEXT: v_mov_b32_e32 v5, s5 -; GCN2-NEXT: .LBB99_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB121_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6337,7 +7509,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB99_1 +; GCN2-NEXT: s_cbranch_execnz .LBB121_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] @@ -6353,7 +7525,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB99_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB121_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6367,7 +7539,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_scalar(ptr inreg %ptr, i64 inr ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB99_1 +; GCN3-NEXT: s_cbranch_execnz .LBB121_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] @@ -6392,7 +7564,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s7 ; GCN1-NEXT: v_mov_b32_e32 v7, s6 -; GCN1-NEXT: .LBB100_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB122_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6406,7 +7578,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_offset_scalar(ptr inreg %out, ; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB100_1 +; GCN1-NEXT: s_cbranch_execnz .LBB122_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] @@ -6427,7 +7599,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s7 ; GCN2-NEXT: v_mov_b32_e32 v7, s6 -; GCN2-NEXT: .LBB100_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB122_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6441,7 +7613,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_offset_scalar(ptr inreg %out, ; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB100_1 +; GCN2-NEXT: s_cbranch_execnz .LBB122_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] @@ -6457,7 +7629,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 ; GCN3-NEXT: v_mov_b32_e32 v5, s5 -; GCN3-NEXT: .LBB100_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB122_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6471,7 +7643,7 @@ define amdgpu_gfx void @flat_atomic_min_i64_noret_offset_scalar(ptr inreg %out, ; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB100_1 +; GCN3-NEXT: s_cbranch_execnz .LBB122_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] @@ -6497,7 +7669,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 ; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: .LBB101_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB123_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 v9, v1 @@ -6511,7 +7683,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB101_1 +; GCN1-NEXT: s_cbranch_execnz .LBB123_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] @@ -6532,7 +7704,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 ; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: .LBB101_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB123_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 v9, v1 @@ -6546,7 +7718,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB101_1 +; GCN2-NEXT: s_cbranch_execnz .LBB123_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] @@ -6562,7 +7734,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB101_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB123_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 v9, v1 @@ -6576,7 +7748,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_scalar(ptr inreg %ptr, i64 inreg ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB101_1 +; GCN3-NEXT: s_cbranch_execnz .LBB123_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] @@ -6601,7 +7773,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN1-NEXT: s_mov_b64 s[34:35], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s7 ; GCN1-NEXT: v_mov_b32_e32 v5, s6 -; GCN1-NEXT: .LBB102_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB124_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 v9, v1 @@ -6615,7 +7787,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB102_1 +; GCN1-NEXT: s_cbranch_execnz .LBB124_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] @@ -6636,7 +7808,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN2-NEXT: s_mov_b64 s[34:35], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s7 ; GCN2-NEXT: v_mov_b32_e32 v5, s6 -; GCN2-NEXT: .LBB102_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB124_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 v9, v1 @@ -6650,7 +7822,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB102_1 +; GCN2-NEXT: s_cbranch_execnz .LBB124_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] @@ -6666,7 +7838,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN3-NEXT: v_mov_b32_e32 v4, s7 ; GCN3-NEXT: v_mov_b32_e32 v5, s6 ; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: .LBB102_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB124_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 v9, v1 @@ -6680,7 +7852,7 @@ define amdgpu_gfx i64 @flat_atomic_min_i64_ret_offset_scalar(ptr inreg %out, i64 ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; 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 .LBB102_1 +; GCN3-NEXT: s_cbranch_execnz .LBB124_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] @@ -6706,7 +7878,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v6, s3 ; GCN1-NEXT: v_mov_b32_e32 v7, s2 -; GCN1-NEXT: .LBB103_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB125_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] @@ -6720,7 +7892,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB103_1 +; GCN1-NEXT: s_cbranch_execnz .LBB125_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -6740,7 +7912,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v6, s3 ; GCN2-NEXT: v_mov_b32_e32 v7, s2 -; GCN2-NEXT: .LBB103_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB125_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] @@ -6754,7 +7926,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB103_1 +; GCN2-NEXT: s_cbranch_execnz .LBB125_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -6772,7 +7944,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v6, s7 ; GCN3-NEXT: v_mov_b32_e32 v7, s6 -; GCN3-NEXT: .LBB103_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB125_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -6786,7 +7958,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr %out, i64 %in, i64 % ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB103_1 +; GCN3-NEXT: s_cbranch_execnz .LBB125_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -6812,7 +7984,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s5 ; GCN1-NEXT: v_mov_b32_e32 v5, s4 -; GCN1-NEXT: .LBB104_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB126_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 v9, v3 @@ -6826,7 +7998,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB104_1 +; GCN1-NEXT: s_cbranch_execnz .LBB126_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -6849,7 +8021,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s5 ; GCN2-NEXT: v_mov_b32_e32 v5, s4 -; GCN2-NEXT: .LBB104_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB126_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 v9, v3 @@ -6863,7 +8035,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB104_1 +; GCN2-NEXT: s_cbranch_execnz .LBB126_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -6884,7 +8056,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v4, s5 ; GCN3-NEXT: v_mov_b32_e32 v5, s4 -; GCN3-NEXT: .LBB104_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB126_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 v9, v3 @@ -6898,7 +8070,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr %out, ptr %out2, ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB104_1 +; GCN3-NEXT: s_cbranch_execnz .LBB126_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s2 @@ -6926,7 +8098,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr %out, i64 %in) { ; GCN1-NEXT: v_mov_b32_e32 v6, s3 ; GCN1-NEXT: v_mov_b32_e32 v7, s2 ; GCN1-NEXT: v_mov_b32_e32 v4, s0 -; GCN1-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB127_1: ; %atomicrmw.start ; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN1-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] @@ -6940,7 +8112,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr %out, i64 %in) { ; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN1-NEXT: v_mov_b32_e32 v2, v0 ; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB105_1 +; GCN1-NEXT: s_cbranch_execnz .LBB127_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_endpgm ; @@ -6956,7 +8128,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr %out, i64 %in) { ; GCN2-NEXT: v_mov_b32_e32 v6, s3 ; GCN2-NEXT: v_mov_b32_e32 v7, s2 ; GCN2-NEXT: v_mov_b32_e32 v4, s0 -; GCN2-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB127_1: ; %atomicrmw.start ; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN2-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] @@ -6970,7 +8142,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr %out, i64 %in) { ; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN2-NEXT: v_mov_b32_e32 v2, v0 ; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB105_1 +; GCN2-NEXT: s_cbranch_execnz .LBB127_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_endpgm ; @@ -6986,7 +8158,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr %out, i64 %in) { ; GCN3-NEXT: v_mov_b32_e32 v6, s3 ; GCN3-NEXT: v_mov_b32_e32 v7, s2 ; GCN3-NEXT: v_mov_b32_e32 v4, s0 -; GCN3-NEXT: .LBB105_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB127_1: ; %atomicrmw.start ; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 ; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) ; GCN3-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] @@ -7000,7 +8172,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr %out, i64 %in) { ; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GCN3-NEXT: v_mov_b32_e32 v2, v0 ; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB105_1 +; GCN3-NEXT: s_cbranch_execnz .LBB127_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_endpgm entry: @@ -7022,7 +8194,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN1-NEXT: s_mov_b64 s[0:1], 0 ; GCN1-NEXT: v_mov_b32_e32 v4, s5 ; GCN1-NEXT: v_mov_b32_e32 v5, s4 -; GCN1-NEXT: .LBB106_1: ; %atomicrmw.start +; GCN1-NEXT: .LBB128_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 v9, v3 @@ -7036,7 +8208,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN1-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN1-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN1-NEXT: s_cbranch_execnz .LBB106_1 +; GCN1-NEXT: s_cbranch_execnz .LBB128_1 ; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN1-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN1-NEXT: v_mov_b32_e32 v0, s2 @@ -7057,7 +8229,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN2-NEXT: s_mov_b64 s[0:1], 0 ; GCN2-NEXT: v_mov_b32_e32 v4, s5 ; GCN2-NEXT: v_mov_b32_e32 v5, s4 -; GCN2-NEXT: .LBB106_1: ; %atomicrmw.start +; GCN2-NEXT: .LBB128_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 v9, v3 @@ -7071,7 +8243,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN2-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN2-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN2-NEXT: s_cbranch_execnz .LBB106_1 +; GCN2-NEXT: s_cbranch_execnz .LBB128_1 ; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN2-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN2-NEXT: v_mov_b32_e32 v0, s2 @@ -7092,7 +8264,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN3-NEXT: s_mov_b64 s[0:1], 0 ; GCN3-NEXT: v_mov_b32_e32 v4, s5 ; GCN3-NEXT: v_mov_b32_e32 v5, s4 -; GCN3-NEXT: .LBB106_1: ; %atomicrmw.start +; GCN3-NEXT: .LBB128_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 v9, v3 @@ -7106,7 +8278,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr %out, ptr %out2, i64 %i ; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; GCN3-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GCN3-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GCN3-NEXT: s_cbranch_execnz .LBB106_1 +; GCN3-NEXT: s_cbranch_execnz .LBB128_1 ; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end ; GCN3-NEXT: s_or_b64 exec, exec, s[0:1] ; GCN3-NEXT: v_mov_b32_e32 v0, s2 @@ -7120,6 +8292,182 @@ entry: ret void } +define void @flat_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v8, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v7, v[0:1] +; GCN1-NEXT: flat_load_dword v6, v[8:9] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB129_1: ; %atomicrmw.start +; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN1-NEXT: v_mov_b32_e32 v7, v1 +; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN1-NEXT: v_mov_b32_e32 v6, v0 +; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN1-NEXT: s_cbranch_execnz .LBB129_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: flat_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v8, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v9, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v7, v[0:1] +; GCN2-NEXT: flat_load_dword v6, v[8:9] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB129_1: ; %atomicrmw.start +; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[8:9], v[4:7] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] +; GCN2-NEXT: v_mov_b32_e32 v7, v1 +; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN2-NEXT: v_mov_b32_e32 v6, v0 +; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN2-NEXT: s_cbranch_execnz .LBB129_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: flat_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[6:7], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB129_1: ; %atomicrmw.start +; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GCN3-NEXT: v_mov_b32_e32 v7, v5 +; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GCN3-NEXT: s_cbranch_execnz .LBB129_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] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw min ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v4, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 36, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_load_dword v1, v[0:1] +; GCN1-NEXT: flat_load_dword v0, v[4:5] +; GCN1-NEXT: s_mov_b64 s[4:5], 0 +; GCN1-NEXT: .LBB130_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 v9, v1 +; GCN1-NEXT: v_mov_b32_e32 v8, v0 +; GCN1-NEXT: v_cmp_le_i64_e32 vcc, v[8:9], v[2:3] +; GCN1-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN1-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN1-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB130_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: flat_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 36, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_load_dword v1, v[0:1] +; GCN2-NEXT: flat_load_dword v0, v[4:5] +; GCN2-NEXT: s_mov_b64 s[4:5], 0 +; GCN2-NEXT: .LBB130_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 v9, v1 +; GCN2-NEXT: v_mov_b32_e32 v8, v0 +; GCN2-NEXT: v_cmp_le_i64_e32 vcc, v[8:9], v[2:3] +; GCN2-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; GCN2-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; GCN2-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; 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 .LBB130_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: flat_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_load_dwordx2 v[4:5], v[0:1] offset:32 +; GCN3-NEXT: s_mov_b64 s[4:5], 0 +; GCN3-NEXT: .LBB130_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 v7, v5 +; GCN3-NEXT: v_mov_b32_e32 v6, v4 +; GCN3-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GCN3-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GCN3-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GCN3-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; 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 .LBB130_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: v_mov_b32_e32 v1, v5 +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw min ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw uinc_wrap ; --------------------------------------------------------------------- @@ -7416,6 +8764,72 @@ define amdgpu_gfx i64 @flat_atomic_uinc_wrap_i64_ret_offset_scalar(ptr inreg %ou ret i64 %result } +define void @flat_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_inc_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_inc_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_inc_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw uinc_wrap ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_inc_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_inc_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_inc_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw uinc_wrap ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw udec_wrap ; --------------------------------------------------------------------- @@ -7711,3 +9125,71 @@ define amdgpu_gfx i64 @flat_atomic_udec_wrap_i64_ret_offset_scalar(ptr inreg %ou %result = atomicrmw udec_wrap ptr %gep, i64 %in seq_cst ret i64 %result } + +define void @flat_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_dec_x2 v[0:1], v[2:3] +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_dec_x2 v[0:1], v[2:3] +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_dec_x2 v[0:1], v[2:3] offset:32 +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %tmp0 = atomicrmw udec_wrap ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @flat_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access(ptr %out, i64 %in) { +; GCN1-LABEL: flat_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN1: ; %bb.0: +; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN1-NEXT: v_add_i32_e32 v0, vcc, 32, v0 +; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN1-NEXT: flat_atomic_dec_x2 v[0:1], v[0:1], v[2:3] glc +; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN1-NEXT: buffer_wbinvl1_vol +; GCN1-NEXT: s_setpc_b64 s[30:31] +; +; GCN2-LABEL: flat_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN2: ; %bb.0: +; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN2-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GCN2-NEXT: flat_atomic_dec_x2 v[0:1], v[0:1], v[2:3] glc +; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN2-NEXT: buffer_wbinvl1_vol +; GCN2-NEXT: s_setpc_b64 s[30:31] +; +; GCN3-LABEL: flat_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GCN3: ; %bb.0: +; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN3-NEXT: flat_atomic_dec_x2 v[0:1], v[0:1], v[2:3] offset:32 glc +; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; GCN3-NEXT: buffer_wbinvl1_vol +; GCN3-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr %out, i64 4 + %result = atomicrmw udec_wrap ptr %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +!0 = !{} diff --git a/llvm/test/CodeGen/AMDGPU/global-atomics-fp.ll b/llvm/test/CodeGen/AMDGPU/global-atomics-fp.ll index 5889de7faf3e..d10e049444d6 100644 --- a/llvm/test/CodeGen/AMDGPU/global-atomics-fp.ll +++ b/llvm/test/CodeGen/AMDGPU/global-atomics-fp.ll @@ -1933,6 +1933,646 @@ define amdgpu_kernel void @global_atomic_fadd_ret_bf16_system(ptr addrspace(1) % ret void } +define <2 x half> @global_atomic_fadd_ret_v2f16(ptr addrspace(1) %ptr, <2 x half> %val) { +; GFX900-LABEL: global_atomic_fadd_ret_v2f16: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX900-NEXT: global_load_dword v3, v[0:1], off +; GFX900-NEXT: s_mov_b64 s[4:5], 0 +; GFX900-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX900-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_mov_b32_e32 v4, v3 +; GFX900-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX900-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: buffer_wbinvl1_vol +; GFX900-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX900-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX900-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX900-NEXT: s_cbranch_execnz .LBB12_1 +; GFX900-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX900-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX900-NEXT: v_mov_b32_e32 v0, v3 +; GFX900-NEXT: s_setpc_b64 s[30:31] +; +; GFX908-LABEL: global_atomic_fadd_ret_v2f16: +; GFX908: ; %bb.0: +; GFX908-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX908-NEXT: global_load_dword v3, v[0:1], off +; GFX908-NEXT: s_mov_b64 s[4:5], 0 +; GFX908-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX908-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: v_mov_b32_e32 v4, v3 +; GFX908-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX908-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: buffer_wbinvl1_vol +; GFX908-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX908-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX908-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX908-NEXT: s_cbranch_execnz .LBB12_1 +; GFX908-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX908-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX908-NEXT: v_mov_b32_e32 v0, v3 +; GFX908-NEXT: s_setpc_b64 s[30:31] +; +; GFX90A-LABEL: global_atomic_fadd_ret_v2f16: +; GFX90A: ; %bb.0: +; GFX90A-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX90A-NEXT: global_load_dword v3, v[0:1], off +; GFX90A-NEXT: s_mov_b64 s[4:5], 0 +; GFX90A-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: v_mov_b32_e32 v5, v3 +; GFX90A-NEXT: v_pk_add_f16 v4, v5, v2 +; GFX90A-NEXT: global_atomic_cmpswap v3, v[0:1], v[4:5], off glc +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 +; GFX90A-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX90A-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX90A-NEXT: s_cbranch_execnz .LBB12_1 +; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX90A-NEXT: v_mov_b32_e32 v0, v3 +; GFX90A-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: global_atomic_fadd_ret_v2f16: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v3, v[0:1], off +; GFX10-NEXT: s_mov_b32 s4, 0 +; GFX10-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v4, v3 +; GFX10-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX10-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: buffer_gl1_inv +; GFX10-NEXT: buffer_gl0_inv +; GFX10-NEXT: v_cmp_eq_u32_e32 vcc_lo, v3, v4 +; GFX10-NEXT: s_or_b32 s4, vcc_lo, s4 +; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4 +; GFX10-NEXT: s_cbranch_execnz .LBB12_1 +; GFX10-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s4 +; GFX10-NEXT: v_mov_b32_e32 v0, v3 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: global_atomic_fadd_ret_v2f16: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v3, v[0:1], off +; GFX11-NEXT: s_mov_b32 s0, 0 +; GFX11-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v4, v3 +; GFX11-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX11-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX11-NEXT: global_atomic_cmpswap_b32 v3, v[0:1], v[3:4], off glc +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: buffer_gl1_inv +; GFX11-NEXT: buffer_gl0_inv +; GFX11-NEXT: v_cmp_eq_u32_e32 vcc_lo, v3, v4 +; GFX11-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX11-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX11-NEXT: s_cbranch_execnz .LBB12_1 +; GFX11-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX11-NEXT: s_or_b32 exec_lo, exec_lo, s0 +; GFX11-NEXT: v_mov_b32_e32 v0, v3 +; GFX11-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %val syncscope("agent") seq_cst + ret <2 x half> %result +} + +define void @global_atomic_fadd_noret_v2f16(ptr addrspace(1) %ptr, <2 x half> %val) { +; GFX900-LABEL: global_atomic_fadd_noret_v2f16: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX900-NEXT: global_load_dword v4, v[0:1], off +; GFX900-NEXT: s_mov_b64 s[4:5], 0 +; GFX900-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX900-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX900-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: buffer_wbinvl1_vol +; GFX900-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX900-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX900-NEXT: v_mov_b32_e32 v4, v3 +; GFX900-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX900-NEXT: s_cbranch_execnz .LBB13_1 +; GFX900-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX900-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX900-NEXT: s_setpc_b64 s[30:31] +; +; GFX908-LABEL: global_atomic_fadd_noret_v2f16: +; GFX908: ; %bb.0: +; GFX908-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX908-NEXT: global_load_dword v4, v[0:1], off +; GFX908-NEXT: s_mov_b64 s[4:5], 0 +; GFX908-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX908-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX908-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: buffer_wbinvl1_vol +; GFX908-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX908-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX908-NEXT: v_mov_b32_e32 v4, v3 +; GFX908-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX908-NEXT: s_cbranch_execnz .LBB13_1 +; GFX908-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX908-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX908-NEXT: s_setpc_b64 s[30:31] +; +; GFX90A-LABEL: global_atomic_fadd_noret_v2f16: +; GFX90A: ; %bb.0: +; GFX90A-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX90A-NEXT: global_load_dword v5, v[0:1], off +; GFX90A-NEXT: s_mov_b64 s[4:5], 0 +; GFX90A-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: v_pk_add_f16 v4, v5, v2 +; GFX90A-NEXT: global_atomic_cmpswap v3, v[0:1], v[4:5], off glc +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 +; GFX90A-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX90A-NEXT: v_mov_b32_e32 v5, v3 +; GFX90A-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX90A-NEXT: s_cbranch_execnz .LBB13_1 +; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX90A-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: global_atomic_fadd_noret_v2f16: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v4, v[0:1], off +; GFX10-NEXT: s_mov_b32 s4, 0 +; GFX10-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX10-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: buffer_gl1_inv +; GFX10-NEXT: buffer_gl0_inv +; GFX10-NEXT: v_cmp_eq_u32_e32 vcc_lo, v3, v4 +; GFX10-NEXT: v_mov_b32_e32 v4, v3 +; GFX10-NEXT: s_or_b32 s4, vcc_lo, s4 +; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4 +; GFX10-NEXT: s_cbranch_execnz .LBB13_1 +; GFX10-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s4 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: global_atomic_fadd_noret_v2f16: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v4, v[0:1], off +; GFX11-NEXT: s_mov_b32 s0, 0 +; GFX11-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_pk_add_f16 v3, v4, v2 +; GFX11-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX11-NEXT: global_atomic_cmpswap_b32 v3, v[0:1], v[3:4], off glc +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: buffer_gl1_inv +; GFX11-NEXT: buffer_gl0_inv +; GFX11-NEXT: v_cmp_eq_u32_e32 vcc_lo, v3, v4 +; GFX11-NEXT: v_mov_b32_e32 v4, v3 +; GFX11-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX11-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX11-NEXT: s_cbranch_execnz .LBB13_1 +; GFX11-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX11-NEXT: s_or_b32 exec_lo, exec_lo, s0 +; GFX11-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %val syncscope("agent") seq_cst + ret void +} + +define <2 x bfloat> @global_atomic_fadd_ret_v2bf16(ptr addrspace(1) %ptr, <2 x bfloat> %val) { +; GFX900-LABEL: global_atomic_fadd_ret_v2bf16: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX900-NEXT: global_load_dword v3, v[0:1], off +; GFX900-NEXT: s_mov_b64 s[6:7], 0 +; GFX900-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX900-NEXT: s_movk_i32 s8, 0x7fff +; GFX900-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX900-NEXT: s_mov_b32 s9, 0x7060302 +; GFX900-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX900-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_mov_b32_e32 v6, v3 +; GFX900-NEXT: v_lshlrev_b32_e32 v3, 16, v6 +; GFX900-NEXT: v_and_b32_e32 v5, 0xffff0000, v6 +; GFX900-NEXT: v_add_f32_e32 v3, v3, v4 +; GFX900-NEXT: v_add_f32_e32 v5, v5, v2 +; GFX900-NEXT: v_bfe_u32 v7, v3, 16, 1 +; GFX900-NEXT: v_bfe_u32 v9, v5, 16, 1 +; GFX900-NEXT: v_or_b32_e32 v8, 0x400000, v3 +; GFX900-NEXT: v_or_b32_e32 v10, 0x400000, v5 +; GFX900-NEXT: v_add3_u32 v7, v7, v3, s8 +; GFX900-NEXT: v_add3_u32 v9, v9, v5, s8 +; GFX900-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; GFX900-NEXT: v_cmp_u_f32_e64 s[4:5], v3, v3 +; GFX900-NEXT: v_cndmask_b32_e64 v3, v7, v8, s[4:5] +; GFX900-NEXT: v_cndmask_b32_e32 v5, v9, v10, vcc +; GFX900-NEXT: v_perm_b32 v5, v5, v3, s9 +; GFX900-NEXT: global_atomic_cmpswap v3, v[0:1], v[5:6], off glc +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: buffer_wbinvl1_vol +; GFX900-NEXT: v_cmp_eq_u32_e32 vcc, v3, v6 +; GFX900-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX900-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX900-NEXT: s_cbranch_execnz .LBB14_1 +; GFX900-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX900-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX900-NEXT: v_mov_b32_e32 v0, v3 +; GFX900-NEXT: s_setpc_b64 s[30:31] +; +; GFX908-LABEL: global_atomic_fadd_ret_v2bf16: +; GFX908: ; %bb.0: +; GFX908-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX908-NEXT: global_load_dword v3, v[0:1], off +; GFX908-NEXT: s_mov_b64 s[6:7], 0 +; GFX908-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX908-NEXT: s_movk_i32 s8, 0x7fff +; GFX908-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX908-NEXT: s_mov_b32 s9, 0x7060302 +; GFX908-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX908-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: v_mov_b32_e32 v6, v3 +; GFX908-NEXT: v_lshlrev_b32_e32 v3, 16, v6 +; GFX908-NEXT: v_and_b32_e32 v5, 0xffff0000, v6 +; GFX908-NEXT: v_add_f32_e32 v3, v3, v4 +; GFX908-NEXT: v_add_f32_e32 v5, v5, v2 +; GFX908-NEXT: v_bfe_u32 v7, v3, 16, 1 +; GFX908-NEXT: v_bfe_u32 v9, v5, 16, 1 +; GFX908-NEXT: v_or_b32_e32 v8, 0x400000, v3 +; GFX908-NEXT: v_or_b32_e32 v10, 0x400000, v5 +; GFX908-NEXT: v_add3_u32 v7, v7, v3, s8 +; GFX908-NEXT: v_add3_u32 v9, v9, v5, s8 +; GFX908-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; GFX908-NEXT: v_cmp_u_f32_e64 s[4:5], v3, v3 +; GFX908-NEXT: v_cndmask_b32_e64 v3, v7, v8, s[4:5] +; GFX908-NEXT: v_cndmask_b32_e32 v5, v9, v10, vcc +; GFX908-NEXT: v_perm_b32 v5, v5, v3, s9 +; GFX908-NEXT: global_atomic_cmpswap v3, v[0:1], v[5:6], off glc +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: buffer_wbinvl1_vol +; GFX908-NEXT: v_cmp_eq_u32_e32 vcc, v3, v6 +; GFX908-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX908-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX908-NEXT: s_cbranch_execnz .LBB14_1 +; GFX908-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX908-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX908-NEXT: v_mov_b32_e32 v0, v3 +; GFX908-NEXT: s_setpc_b64 s[30:31] +; +; GFX90A-LABEL: global_atomic_fadd_ret_v2bf16: +; GFX90A: ; %bb.0: +; GFX90A-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX90A-NEXT: global_load_dword v3, v[0:1], off +; GFX90A-NEXT: s_mov_b64 s[6:7], 0 +; GFX90A-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX90A-NEXT: s_movk_i32 s8, 0x7fff +; GFX90A-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX90A-NEXT: s_mov_b32 s9, 0x7060302 +; GFX90A-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: v_mov_b32_e32 v7, v3 +; GFX90A-NEXT: v_lshlrev_b32_e32 v3, 16, v7 +; GFX90A-NEXT: v_and_b32_e32 v5, 0xffff0000, v7 +; GFX90A-NEXT: v_add_f32_e32 v3, v3, v4 +; GFX90A-NEXT: v_add_f32_e32 v5, v5, v2 +; GFX90A-NEXT: v_bfe_u32 v6, v3, 16, 1 +; GFX90A-NEXT: v_bfe_u32 v9, v5, 16, 1 +; GFX90A-NEXT: v_or_b32_e32 v8, 0x400000, v3 +; GFX90A-NEXT: v_or_b32_e32 v10, 0x400000, v5 +; GFX90A-NEXT: v_add3_u32 v6, v6, v3, s8 +; GFX90A-NEXT: v_add3_u32 v9, v9, v5, s8 +; GFX90A-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; GFX90A-NEXT: v_cmp_u_f32_e64 s[4:5], v3, v3 +; GFX90A-NEXT: v_cndmask_b32_e64 v3, v6, v8, s[4:5] +; GFX90A-NEXT: v_cndmask_b32_e32 v5, v9, v10, vcc +; GFX90A-NEXT: v_perm_b32 v6, v5, v3, s9 +; GFX90A-NEXT: global_atomic_cmpswap v3, v[0:1], v[6:7], off glc +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, v3, v7 +; GFX90A-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX90A-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX90A-NEXT: s_cbranch_execnz .LBB14_1 +; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX90A-NEXT: v_mov_b32_e32 v0, v3 +; GFX90A-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: global_atomic_fadd_ret_v2bf16: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v3, v[0:1], off +; GFX10-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX10-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX10-NEXT: s_mov_b32 s5, 0 +; GFX10-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v6, v3 +; GFX10-NEXT: v_lshlrev_b32_e32 v3, 16, v6 +; GFX10-NEXT: v_and_b32_e32 v5, 0xffff0000, v6 +; GFX10-NEXT: v_add_f32_e32 v3, v3, v4 +; GFX10-NEXT: v_add_f32_e32 v5, v5, v2 +; GFX10-NEXT: v_bfe_u32 v7, v3, 16, 1 +; GFX10-NEXT: v_bfe_u32 v8, v5, 16, 1 +; GFX10-NEXT: v_or_b32_e32 v9, 0x400000, v3 +; GFX10-NEXT: v_or_b32_e32 v10, 0x400000, v5 +; GFX10-NEXT: v_cmp_u_f32_e32 vcc_lo, v5, v5 +; GFX10-NEXT: v_add3_u32 v7, v7, v3, 0x7fff +; GFX10-NEXT: v_add3_u32 v8, v8, v5, 0x7fff +; GFX10-NEXT: v_cmp_u_f32_e64 s4, v3, v3 +; GFX10-NEXT: v_cndmask_b32_e32 v5, v8, v10, vcc_lo +; GFX10-NEXT: v_cndmask_b32_e64 v3, v7, v9, s4 +; GFX10-NEXT: v_perm_b32 v5, v5, v3, 0x7060302 +; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX10-NEXT: global_atomic_cmpswap v3, v[0:1], v[5:6], off glc +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: buffer_gl1_inv +; GFX10-NEXT: buffer_gl0_inv +; GFX10-NEXT: v_cmp_eq_u32_e32 vcc_lo, v3, v6 +; GFX10-NEXT: s_or_b32 s5, vcc_lo, s5 +; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s5 +; GFX10-NEXT: s_cbranch_execnz .LBB14_1 +; GFX10-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s5 +; GFX10-NEXT: v_mov_b32_e32 v0, v3 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: global_atomic_fadd_ret_v2bf16: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v3, v[0:1], off +; GFX11-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX11-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX11-NEXT: s_mov_b32 s1, 0 +; GFX11-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX11-NEXT: .p2align 6 +; GFX11-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_mov_b32_e32 v6, v3 +; GFX11-NEXT: v_and_b32_e32 v5, 0xffff0000, v6 +; GFX11-NEXT: v_add_f32_e32 v5, v5, v2 +; GFX11-NEXT: v_lshlrev_b32_e32 v3, 16, v6 +; GFX11-NEXT: v_bfe_u32 v8, v5, 16, 1 +; GFX11-NEXT: v_add_f32_e32 v3, v3, v4 +; GFX11-NEXT: v_or_b32_e32 v10, 0x400000, v5 +; GFX11-NEXT: v_cmp_u_f32_e32 vcc_lo, v5, v5 +; GFX11-NEXT: v_add3_u32 v8, v8, v5, 0x7fff +; GFX11-NEXT: v_bfe_u32 v7, v3, 16, 1 +; GFX11-NEXT: v_or_b32_e32 v9, 0x400000, v3 +; GFX11-NEXT: v_cmp_u_f32_e64 s0, v3, v3 +; GFX11-NEXT: v_cndmask_b32_e32 v5, v8, v10, vcc_lo +; GFX11-NEXT: v_add3_u32 v7, v7, v3, 0x7fff +; GFX11-NEXT: v_cndmask_b32_e64 v3, v7, v9, s0 +; GFX11-NEXT: v_perm_b32 v5, v5, v3, 0x7060302 +; GFX11-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX11-NEXT: global_atomic_cmpswap_b32 v3, v[0:1], v[5:6], off glc +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: buffer_gl1_inv +; GFX11-NEXT: buffer_gl0_inv +; GFX11-NEXT: v_cmp_eq_u32_e32 vcc_lo, v3, v6 +; GFX11-NEXT: s_or_b32 s1, vcc_lo, s1 +; GFX11-NEXT: s_and_not1_b32 exec_lo, exec_lo, s1 +; GFX11-NEXT: s_cbranch_execnz .LBB14_1 +; GFX11-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX11-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX11-NEXT: s_or_b32 exec_lo, exec_lo, s1 +; GFX11-NEXT: v_mov_b32_e32 v0, v3 +; GFX11-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %val syncscope("agent") seq_cst + ret <2 x bfloat> %result +} + +define void @global_atomic_fadd_noret_v2bf16(ptr addrspace(1) %ptr, <2 x bfloat> %val) { +; GFX900-LABEL: global_atomic_fadd_noret_v2bf16: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX900-NEXT: global_load_dword v3, v[0:1], off +; GFX900-NEXT: s_mov_b64 s[6:7], 0 +; GFX900-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX900-NEXT: s_movk_i32 s8, 0x7fff +; GFX900-NEXT: v_and_b32_e32 v5, 0xffff0000, v2 +; GFX900-NEXT: s_mov_b32 s9, 0x7060302 +; GFX900-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX900-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: v_lshlrev_b32_e32 v2, 16, v3 +; GFX900-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX900-NEXT: v_add_f32_e32 v2, v2, v4 +; GFX900-NEXT: v_add_f32_e32 v6, v6, v5 +; GFX900-NEXT: v_bfe_u32 v7, v2, 16, 1 +; GFX900-NEXT: v_bfe_u32 v9, v6, 16, 1 +; GFX900-NEXT: v_or_b32_e32 v8, 0x400000, v2 +; GFX900-NEXT: v_or_b32_e32 v10, 0x400000, v6 +; GFX900-NEXT: v_add3_u32 v7, v7, v2, s8 +; GFX900-NEXT: v_add3_u32 v9, v9, v6, s8 +; GFX900-NEXT: v_cmp_u_f32_e32 vcc, v6, v6 +; GFX900-NEXT: v_cmp_u_f32_e64 s[4:5], v2, v2 +; GFX900-NEXT: v_cndmask_b32_e64 v2, v7, v8, s[4:5] +; GFX900-NEXT: v_cndmask_b32_e32 v6, v9, v10, vcc +; GFX900-NEXT: v_perm_b32 v2, v6, v2, s9 +; GFX900-NEXT: global_atomic_cmpswap v2, v[0:1], v[2:3], off glc +; GFX900-NEXT: s_waitcnt vmcnt(0) +; GFX900-NEXT: buffer_wbinvl1_vol +; GFX900-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 +; GFX900-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX900-NEXT: v_mov_b32_e32 v3, v2 +; GFX900-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX900-NEXT: s_cbranch_execnz .LBB15_1 +; GFX900-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX900-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX900-NEXT: s_setpc_b64 s[30:31] +; +; GFX908-LABEL: global_atomic_fadd_noret_v2bf16: +; GFX908: ; %bb.0: +; GFX908-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX908-NEXT: global_load_dword v3, v[0:1], off +; GFX908-NEXT: s_mov_b64 s[6:7], 0 +; GFX908-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX908-NEXT: s_movk_i32 s8, 0x7fff +; GFX908-NEXT: v_and_b32_e32 v5, 0xffff0000, v2 +; GFX908-NEXT: s_mov_b32 s9, 0x7060302 +; GFX908-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX908-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: v_lshlrev_b32_e32 v2, 16, v3 +; GFX908-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX908-NEXT: v_add_f32_e32 v2, v2, v4 +; GFX908-NEXT: v_add_f32_e32 v6, v6, v5 +; GFX908-NEXT: v_bfe_u32 v7, v2, 16, 1 +; GFX908-NEXT: v_bfe_u32 v9, v6, 16, 1 +; GFX908-NEXT: v_or_b32_e32 v8, 0x400000, v2 +; GFX908-NEXT: v_or_b32_e32 v10, 0x400000, v6 +; GFX908-NEXT: v_add3_u32 v7, v7, v2, s8 +; GFX908-NEXT: v_add3_u32 v9, v9, v6, s8 +; GFX908-NEXT: v_cmp_u_f32_e32 vcc, v6, v6 +; GFX908-NEXT: v_cmp_u_f32_e64 s[4:5], v2, v2 +; GFX908-NEXT: v_cndmask_b32_e64 v2, v7, v8, s[4:5] +; GFX908-NEXT: v_cndmask_b32_e32 v6, v9, v10, vcc +; GFX908-NEXT: v_perm_b32 v2, v6, v2, s9 +; GFX908-NEXT: global_atomic_cmpswap v2, v[0:1], v[2:3], off glc +; GFX908-NEXT: s_waitcnt vmcnt(0) +; GFX908-NEXT: buffer_wbinvl1_vol +; GFX908-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 +; GFX908-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX908-NEXT: v_mov_b32_e32 v3, v2 +; GFX908-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX908-NEXT: s_cbranch_execnz .LBB15_1 +; GFX908-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX908-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX908-NEXT: s_setpc_b64 s[30:31] +; +; GFX90A-LABEL: global_atomic_fadd_noret_v2bf16: +; GFX90A: ; %bb.0: +; GFX90A-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX90A-NEXT: global_load_dword v3, v[0:1], off +; GFX90A-NEXT: s_mov_b64 s[6:7], 0 +; GFX90A-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX90A-NEXT: s_movk_i32 s8, 0x7fff +; GFX90A-NEXT: v_and_b32_e32 v5, 0xffff0000, v2 +; GFX90A-NEXT: s_mov_b32 s9, 0x7060302 +; GFX90A-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: v_lshlrev_b32_e32 v2, 16, v3 +; GFX90A-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX90A-NEXT: v_add_f32_e32 v2, v2, v4 +; GFX90A-NEXT: v_add_f32_e32 v6, v6, v5 +; GFX90A-NEXT: v_bfe_u32 v7, v2, 16, 1 +; GFX90A-NEXT: v_bfe_u32 v9, v6, 16, 1 +; GFX90A-NEXT: v_or_b32_e32 v8, 0x400000, v2 +; GFX90A-NEXT: v_or_b32_e32 v10, 0x400000, v6 +; GFX90A-NEXT: v_add3_u32 v7, v7, v2, s8 +; GFX90A-NEXT: v_add3_u32 v9, v9, v6, s8 +; GFX90A-NEXT: v_cmp_u_f32_e32 vcc, v6, v6 +; GFX90A-NEXT: v_cmp_u_f32_e64 s[4:5], v2, v2 +; GFX90A-NEXT: v_cndmask_b32_e64 v2, v7, v8, s[4:5] +; GFX90A-NEXT: v_cndmask_b32_e32 v6, v9, v10, vcc +; GFX90A-NEXT: v_perm_b32 v2, v6, v2, s9 +; GFX90A-NEXT: global_atomic_cmpswap v2, v[0:1], v[2:3], off glc +; GFX90A-NEXT: s_waitcnt vmcnt(0) +; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 +; GFX90A-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX90A-NEXT: v_mov_b32_e32 v3, v2 +; GFX90A-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX90A-NEXT: s_cbranch_execnz .LBB15_1 +; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX90A-NEXT: s_setpc_b64 s[30:31] +; +; GFX10-LABEL: global_atomic_fadd_noret_v2bf16: +; GFX10: ; %bb.0: +; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX10-NEXT: global_load_dword v3, v[0:1], off +; GFX10-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX10-NEXT: v_and_b32_e32 v5, 0xffff0000, v2 +; GFX10-NEXT: s_mov_b32 s5, 0 +; GFX10-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_lshlrev_b32_e32 v2, 16, v3 +; GFX10-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX10-NEXT: v_add_f32_e32 v2, v2, v4 +; GFX10-NEXT: v_add_f32_e32 v6, v6, v5 +; GFX10-NEXT: v_bfe_u32 v7, v2, 16, 1 +; GFX10-NEXT: v_bfe_u32 v8, v6, 16, 1 +; GFX10-NEXT: v_or_b32_e32 v9, 0x400000, v2 +; GFX10-NEXT: v_or_b32_e32 v10, 0x400000, v6 +; GFX10-NEXT: v_cmp_u_f32_e32 vcc_lo, v6, v6 +; GFX10-NEXT: v_add3_u32 v7, v7, v2, 0x7fff +; GFX10-NEXT: v_add3_u32 v8, v8, v6, 0x7fff +; GFX10-NEXT: v_cmp_u_f32_e64 s4, v2, v2 +; GFX10-NEXT: v_cndmask_b32_e32 v6, v8, v10, vcc_lo +; GFX10-NEXT: v_cndmask_b32_e64 v2, v7, v9, s4 +; GFX10-NEXT: v_perm_b32 v2, v6, v2, 0x7060302 +; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX10-NEXT: global_atomic_cmpswap v2, v[0:1], v[2:3], off glc +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: buffer_gl1_inv +; GFX10-NEXT: buffer_gl0_inv +; GFX10-NEXT: v_cmp_eq_u32_e32 vcc_lo, v2, v3 +; GFX10-NEXT: v_mov_b32_e32 v3, v2 +; GFX10-NEXT: s_or_b32 s5, vcc_lo, s5 +; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s5 +; GFX10-NEXT: s_cbranch_execnz .LBB15_1 +; GFX10-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s5 +; GFX10-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: global_atomic_fadd_noret_v2bf16: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: global_load_b32 v3, v[0:1], off +; GFX11-NEXT: v_lshlrev_b32_e32 v4, 16, v2 +; GFX11-NEXT: v_and_b32_e32 v5, 0xffff0000, v2 +; GFX11-NEXT: s_mov_b32 s1, 0 +; GFX11-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX11-NEXT: .p2align 6 +; GFX11-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_lshlrev_b32_e32 v2, 16, v3 +; GFX11-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX11-NEXT: v_add_f32_e32 v2, v2, v4 +; GFX11-NEXT: v_add_f32_e32 v6, v6, v5 +; GFX11-NEXT: v_bfe_u32 v7, v2, 16, 1 +; GFX11-NEXT: v_bfe_u32 v8, v6, 16, 1 +; GFX11-NEXT: v_or_b32_e32 v9, 0x400000, v2 +; GFX11-NEXT: v_or_b32_e32 v10, 0x400000, v6 +; GFX11-NEXT: v_cmp_u_f32_e32 vcc_lo, v6, v6 +; GFX11-NEXT: v_add3_u32 v7, v7, v2, 0x7fff +; GFX11-NEXT: v_add3_u32 v8, v8, v6, 0x7fff +; GFX11-NEXT: v_cmp_u_f32_e64 s0, v2, v2 +; GFX11-NEXT: v_cndmask_b32_e32 v6, v8, v10, vcc_lo +; GFX11-NEXT: v_cndmask_b32_e64 v2, v7, v9, s0 +; GFX11-NEXT: v_perm_b32 v2, v6, v2, 0x7060302 +; GFX11-NEXT: s_waitcnt_vscnt null, 0x0 +; GFX11-NEXT: global_atomic_cmpswap_b32 v2, v[0:1], v[2:3], off glc +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: buffer_gl1_inv +; GFX11-NEXT: buffer_gl0_inv +; GFX11-NEXT: v_cmp_eq_u32_e32 vcc_lo, v2, v3 +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: s_or_b32 s1, vcc_lo, s1 +; GFX11-NEXT: s_and_not1_b32 exec_lo, exec_lo, s1 +; GFX11-NEXT: s_cbranch_execnz .LBB15_1 +; GFX11-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX11-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX11-NEXT: s_or_b32 exec_lo, exec_lo, s1 +; GFX11-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %val syncscope("agent") seq_cst + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #1 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "target-cpu"="gfx803" "target-features"="+atomic-fadd-no-rtn-insts" "amdgpu-unsafe-fp-atomics"="true" } attributes #2 = { "amdgpu-unsafe-fp-atomics"="true" } diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll index 4598d23e088b..4ec3ac25b2f1 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll @@ -353,6 +353,79 @@ define amdgpu_gfx i32 @global_atomic_xchg_i32_ret_offset_scalar(ptr addrspace(1) ret i32 %result } +define void @global_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw xchg ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw xchg ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw xchg f32 ; --------------------------------------------------------------------- @@ -703,6 +776,79 @@ define amdgpu_gfx float @global_atomic_xchg_f32_ret_offset_scalar(ptr addrspace( ret float %result } +define void @global_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, float %in) { +; SI-LABEL: global_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_f32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw xchg ptr addrspace(1) %gep, float %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define float @global_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, float %in) { +; SI-LABEL: global_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_f32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw xchg ptr addrspace(1) %gep, float %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %result +} + ; --------------------------------------------------------------------- ; atomicrmw add ; --------------------------------------------------------------------- @@ -1053,6 +1199,79 @@ define amdgpu_gfx i32 @global_atomic_add_i32_ret_offset_scalar(ptr addrspace(1) ret i32 %result } +define void @global_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_add v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_add_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_add v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw add ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_add v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_add_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_add v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw add ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw sub ; --------------------------------------------------------------------- @@ -1440,6 +1659,79 @@ define i32 @global_atomic_sub_0_i32_ret(ptr addrspace(1) %ptr) { ret i32 %result } +define void @global_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_sub v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_sub v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_sub_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_sub v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw sub ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_sub v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_sub v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_sub_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_sub v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw sub ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw and ; --------------------------------------------------------------------- @@ -1790,25 +2082,98 @@ define amdgpu_gfx i32 @global_atomic_and_i32_ret_offset_scalar(ptr addrspace(1) ret i32 %result } -; --------------------------------------------------------------------- -; atomicrmw nand -; --------------------------------------------------------------------- - -define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { -; SI-LABEL: global_atomic_nand_i32_noret: +define void @global_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 -; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB41_1: ; %atomicrmw.start -; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: buffer_atomic_and v2, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_and_b32_e32 v3, v4, v2 -; SI-NEXT: v_not_b32_e32 v3, v3 +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_and v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_and_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_and v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw and ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_and v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_and v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_and_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_and v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw and ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + +; --------------------------------------------------------------------- +; atomicrmw nand +; --------------------------------------------------------------------- + +define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { +; SI-LABEL: global_atomic_nand_i32_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB51_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v3, v4, v2 +; SI-NEXT: v_not_b32_e32 v3, v3 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: v_mov_b32_e32 v6, v4 ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -1819,7 +2184,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB41_1 +; SI-NEXT: s_cbranch_execnz .LBB51_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -1830,7 +2195,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB41_1: ; %atomicrmw.start +; VI-NEXT: .LBB51_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1842,7 +2207,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB41_1 +; VI-NEXT: s_cbranch_execnz .LBB51_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -1852,7 +2217,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB41_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB51_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1864,7 +2229,7 @@ define void @global_atomic_nand_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB41_1 +; GFX9-NEXT: s_cbranch_execnz .LBB51_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -1882,7 +2247,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB42_1: ; %atomicrmw.start +; SI-NEXT: .LBB52_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1897,7 +2262,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB42_1 +; SI-NEXT: s_cbranch_execnz .LBB52_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -1910,7 +2275,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB42_1: ; %atomicrmw.start +; VI-NEXT: .LBB52_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1922,7 +2287,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB42_1 +; VI-NEXT: s_cbranch_execnz .LBB52_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -1932,7 +2297,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB42_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB52_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v3, v4, v2 @@ -1944,7 +2309,7 @@ define void @global_atomic_nand_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB42_1 +; GFX9-NEXT: s_cbranch_execnz .LBB52_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -1963,7 +2328,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB43_1: ; %atomicrmw.start +; SI-NEXT: .LBB53_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -1978,7 +2343,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB43_1 +; SI-NEXT: s_cbranch_execnz .LBB53_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -1990,7 +2355,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB43_1: ; %atomicrmw.start +; VI-NEXT: .LBB53_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -2002,7 +2367,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB43_1 +; VI-NEXT: s_cbranch_execnz .LBB53_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -2013,7 +2378,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB43_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB53_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -2025,7 +2390,7 @@ define i32 @global_atomic_nand_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB43_1 +; GFX9-NEXT: s_cbranch_execnz .LBB53_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -2044,7 +2409,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB44_1: ; %atomicrmw.start +; SI-NEXT: .LBB54_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -2059,7 +2424,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB44_1 +; SI-NEXT: s_cbranch_execnz .LBB54_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -2073,7 +2438,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB44_1: ; %atomicrmw.start +; VI-NEXT: .LBB54_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -2085,7 +2450,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB44_1 +; VI-NEXT: s_cbranch_execnz .LBB54_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2095,7 +2460,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB44_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB54_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -2107,7 +2472,7 @@ define i32 @global_atomic_nand_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB44_1 +; GFX9-NEXT: s_cbranch_execnz .LBB54_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -2132,7 +2497,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB45_1: ; %atomicrmw.start +; SI-NEXT: .LBB55_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v0, s34, v1 @@ -2147,7 +2512,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB45_1 +; SI-NEXT: s_cbranch_execnz .LBB55_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -2165,7 +2530,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB45_1: ; %atomicrmw.start +; VI-NEXT: .LBB55_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v2, s6, v3 @@ -2177,7 +2542,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB45_1 +; VI-NEXT: s_cbranch_execnz .LBB55_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2188,7 +2553,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB45_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB55_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v0, s6, v1 @@ -2200,7 +2565,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB45_1 +; GFX9-NEXT: s_cbranch_execnz .LBB55_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2223,7 +2588,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB46_1: ; %atomicrmw.start +; SI-NEXT: .LBB56_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v0, s34, v1 @@ -2238,7 +2603,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB46_1 +; SI-NEXT: s_cbranch_execnz .LBB56_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -2258,7 +2623,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB46_1: ; %atomicrmw.start +; VI-NEXT: .LBB56_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v2, s6, v3 @@ -2270,7 +2635,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB46_1 +; VI-NEXT: s_cbranch_execnz .LBB56_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2281,7 +2646,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB46_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB56_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v0, s6, v1 @@ -2293,7 +2658,7 @@ define amdgpu_gfx void @global_atomic_nand_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB46_1 +; GFX9-NEXT: s_cbranch_execnz .LBB56_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2317,7 +2682,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB47_1: ; %atomicrmw.start +; SI-NEXT: .LBB57_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -2332,7 +2697,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB47_1 +; SI-NEXT: s_cbranch_execnz .LBB57_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -2352,7 +2717,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB47_1: ; %atomicrmw.start +; VI-NEXT: .LBB57_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -2364,7 +2729,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB47_1 +; VI-NEXT: s_cbranch_execnz .LBB57_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2375,7 +2740,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB47_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB57_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -2387,7 +2752,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB47_1 +; GFX9-NEXT: s_cbranch_execnz .LBB57_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2410,7 +2775,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB48_1: ; %atomicrmw.start +; SI-NEXT: .LBB58_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -2425,7 +2790,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB48_1 +; SI-NEXT: s_cbranch_execnz .LBB58_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -2445,7 +2810,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB48_1: ; %atomicrmw.start +; VI-NEXT: .LBB58_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -2457,7 +2822,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB48_1 +; VI-NEXT: s_cbranch_execnz .LBB58_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2468,7 +2833,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB48_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB58_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -2480,7 +2845,7 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB48_1 +; GFX9-NEXT: s_cbranch_execnz .LBB58_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2489,6 +2854,170 @@ define amdgpu_gfx i32 @global_atomic_nand_i32_ret_offset_scalar(ptr addrspace(1) ret i32 %result } +define void @global_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB59_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v3, v4, v2 +; SI-NEXT: v_not_b32_e32 v3, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v4 +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB59_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v4, v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB59_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_and_b32_e32 v3, v4, v2 +; VI-NEXT: v_not_b32_e32 v3, v3 +; VI-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v4, v3 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB59_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_nand_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB59_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_and_b32_e32 v3, v4, v2 +; GFX9-NEXT: v_not_b32_e32 v3, v3 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB59_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw nand ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB60_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_and_b32_e32 v3, v5, v2 +; SI-NEXT: v_not_b32_e32 v4, v3 +; SI-NEXT: v_mov_b32_e32 v3, v4 +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: buffer_atomic_cmpswap v[3:4], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB60_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: v_mov_b32_e32 v0, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[3:4] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB60_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, v0 +; VI-NEXT: v_and_b32_e32 v0, v1, v2 +; VI-NEXT: v_not_b32_e32 v0, v0 +; VI-NEXT: flat_atomic_cmpswap v0, v[3:4], v[0:1] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB60_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_nand_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB60_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: v_and_b32_e32 v3, v4, v2 +; GFX9-NEXT: v_not_b32_e32 v3, v3 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB60_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v3 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw nand ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw or ; --------------------------------------------------------------------- @@ -2876,95 +3405,168 @@ define i32 @global_atomic_or_0_i32_ret(ptr addrspace(1) %ptr) { ret i32 %result } -; --------------------------------------------------------------------- -; atomicrmw xor -; --------------------------------------------------------------------- - -define void @global_atomic_xor_i32_noret(ptr addrspace(1) %ptr, i32 %in) { -; SI-LABEL: global_atomic_xor_i32_noret: +define void @global_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: buffer_atomic_or v2, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_xor_i32_noret: +; VI-LABEL: global_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; VI-NEXT: flat_atomic_xor v[0:1], v2 +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_or v[0:1], v2 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: buffer_wbinvl1_vol ; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: global_atomic_xor_i32_noret: +; GFX9-LABEL: global_atomic_or_i32_noret_offset__amdgpu_no_remote_memory_access: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: global_atomic_xor v[0:1], v2, off +; GFX9-NEXT: global_atomic_or v[0:1], v2, off offset:16 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol ; GFX9-NEXT: s_setpc_b64 s[30:31] - %tmp0 = atomicrmw xor ptr addrspace(1) %ptr, i32 %in seq_cst + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw or ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret void } -define void @global_atomic_xor_i32_noret_offset(ptr addrspace(1) %out, i32 %in) { -; SI-LABEL: global_atomic_xor_i32_noret_offset: +define i32 @global_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: buffer_atomic_or v2, v[0:1], s[4:7], 0 addr64 offset:16 glc ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_xor_i32_noret_offset: +; VI-LABEL: global_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; VI-NEXT: flat_atomic_xor v[0:1], v2 +; VI-NEXT: flat_atomic_or v0, v[0:1], v2 glc ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: buffer_wbinvl1_vol ; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: global_atomic_xor_i32_noret_offset: +; GFX9-LABEL: global_atomic_or_i32_ret_offset__amdgpu_no_remote_memory_access: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: global_atomic_xor v[0:1], v2, off offset:16 +; GFX9-NEXT: global_atomic_or v0, v[0:1], v2, off offset:16 glc ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol ; GFX9-NEXT: s_setpc_b64 s[30:31] - %gep = getelementptr i32, ptr addrspace(1) %out, i32 4 - %tmp0 = atomicrmw xor ptr addrspace(1) %gep, i32 %in seq_cst - ret void + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw or ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result } -define i32 @global_atomic_xor_i32_ret(ptr addrspace(1) %ptr, i32 %in) { -; SI-LABEL: global_atomic_xor_i32_ret: +; --------------------------------------------------------------------- +; atomicrmw xor +; --------------------------------------------------------------------- + +define void @global_atomic_xor_i32_noret(ptr addrspace(1) %ptr, i32 %in) { +; SI-LABEL: global_atomic_xor_i32_noret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 -; SI-NEXT: v_mov_b32_e32 v0, v2 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_xor_i32_ret: +; VI-LABEL: global_atomic_xor_i32_noret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: flat_atomic_xor v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i32_noret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor v[0:1], v2, off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %tmp0 = atomicrmw xor ptr addrspace(1) %ptr, i32 %in seq_cst + ret void +} + +define void @global_atomic_xor_i32_noret_offset(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_xor_i32_noret_offset: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i32_noret_offset: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_xor v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i32_noret_offset: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i32 4 + %tmp0 = atomicrmw xor ptr addrspace(1) %gep, i32 %in seq_cst + ret void +} + +define i32 @global_atomic_xor_i32_ret(ptr addrspace(1) %ptr, i32 %in) { +; SI-LABEL: global_atomic_xor_i32_ret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i32_ret: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_atomic_xor v0, v[0:1], v2 glc @@ -3263,6 +3865,79 @@ define i32 @global_atomic_xor_0_i32_ret(ptr addrspace(1) %ptr) { ret i32 %result } +define void @global_atomic_xor_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_xor_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_xor v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw xor ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_xor v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw xor ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw max ; --------------------------------------------------------------------- @@ -3277,7 +3952,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB67_1: ; %atomicrmw.start +; SI-NEXT: .LBB83_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3291,7 +3966,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB67_1 +; SI-NEXT: s_cbranch_execnz .LBB83_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3302,7 +3977,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB67_1: ; %atomicrmw.start +; VI-NEXT: .LBB83_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3313,7 +3988,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB67_1 +; VI-NEXT: s_cbranch_execnz .LBB83_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3323,7 +3998,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB67_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB83_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3334,7 +4009,7 @@ define void @global_atomic_max_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB67_1 +; GFX9-NEXT: s_cbranch_execnz .LBB83_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3352,7 +4027,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB68_1: ; %atomicrmw.start +; SI-NEXT: .LBB84_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3366,7 +4041,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB68_1 +; SI-NEXT: s_cbranch_execnz .LBB84_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3379,7 +4054,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB68_1: ; %atomicrmw.start +; VI-NEXT: .LBB84_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3390,7 +4065,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB68_1 +; VI-NEXT: s_cbranch_execnz .LBB84_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3400,7 +4075,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB68_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB84_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v3, v4, v2 @@ -3411,7 +4086,7 @@ define void @global_atomic_max_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB68_1 +; GFX9-NEXT: s_cbranch_execnz .LBB84_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3430,7 +4105,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB69_1: ; %atomicrmw.start +; SI-NEXT: .LBB85_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -3444,7 +4119,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB69_1 +; SI-NEXT: s_cbranch_execnz .LBB85_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -3456,7 +4131,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB69_1: ; %atomicrmw.start +; VI-NEXT: .LBB85_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -3467,7 +4142,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB69_1 +; VI-NEXT: s_cbranch_execnz .LBB85_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -3478,7 +4153,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB69_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB85_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -3489,7 +4164,7 @@ define i32 @global_atomic_max_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB69_1 +; GFX9-NEXT: s_cbranch_execnz .LBB85_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -3508,7 +4183,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB70_1: ; %atomicrmw.start +; SI-NEXT: .LBB86_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -3522,7 +4197,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB70_1 +; SI-NEXT: s_cbranch_execnz .LBB86_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -3536,7 +4211,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB70_1: ; %atomicrmw.start +; VI-NEXT: .LBB86_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -3547,7 +4222,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB70_1 +; VI-NEXT: s_cbranch_execnz .LBB86_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3557,7 +4232,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB70_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB86_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -3568,7 +4243,7 @@ define i32 @global_atomic_max_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB70_1 +; GFX9-NEXT: s_cbranch_execnz .LBB86_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -3593,7 +4268,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB71_1: ; %atomicrmw.start +; SI-NEXT: .LBB87_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v0, s34, v1 @@ -3607,7 +4282,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB71_1 +; SI-NEXT: s_cbranch_execnz .LBB87_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -3625,7 +4300,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB71_1: ; %atomicrmw.start +; VI-NEXT: .LBB87_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v2, s6, v3 @@ -3636,7 +4311,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB71_1 +; VI-NEXT: s_cbranch_execnz .LBB87_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3647,7 +4322,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB71_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB87_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v0, s6, v1 @@ -3658,7 +4333,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB71_1 +; GFX9-NEXT: s_cbranch_execnz .LBB87_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3681,7 +4356,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB72_1: ; %atomicrmw.start +; SI-NEXT: .LBB88_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_i32_e32 v0, s34, v1 @@ -3695,7 +4370,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB72_1 +; SI-NEXT: s_cbranch_execnz .LBB88_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -3715,7 +4390,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB72_1: ; %atomicrmw.start +; VI-NEXT: .LBB88_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_i32_e32 v2, s6, v3 @@ -3726,7 +4401,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB72_1 +; VI-NEXT: s_cbranch_execnz .LBB88_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3737,7 +4412,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB72_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB88_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_i32_e32 v0, s6, v1 @@ -3748,7 +4423,7 @@ define amdgpu_gfx void @global_atomic_max_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB72_1 +; GFX9-NEXT: s_cbranch_execnz .LBB88_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3772,7 +4447,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB73_1: ; %atomicrmw.start +; SI-NEXT: .LBB89_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -3786,7 +4461,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB73_1 +; SI-NEXT: s_cbranch_execnz .LBB89_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -3806,7 +4481,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB73_1: ; %atomicrmw.start +; VI-NEXT: .LBB89_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -3817,7 +4492,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB73_1 +; VI-NEXT: s_cbranch_execnz .LBB89_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3828,7 +4503,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB73_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB89_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -3839,7 +4514,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB73_1 +; GFX9-NEXT: s_cbranch_execnz .LBB89_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3862,7 +4537,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB74_1: ; %atomicrmw.start +; SI-NEXT: .LBB90_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -3876,7 +4551,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB74_1 +; SI-NEXT: s_cbranch_execnz .LBB90_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -3896,7 +4571,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB74_1: ; %atomicrmw.start +; VI-NEXT: .LBB90_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -3907,7 +4582,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB74_1 +; VI-NEXT: s_cbranch_execnz .LBB90_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3918,7 +4593,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB74_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB90_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -3929,7 +4604,7 @@ define amdgpu_gfx i32 @global_atomic_max_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB74_1 +; GFX9-NEXT: s_cbranch_execnz .LBB90_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3954,7 +4629,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB75_1: ; %atomicrmw.start +; SI-NEXT: .LBB91_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -3967,7 +4642,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB75_1 +; SI-NEXT: s_cbranch_execnz .LBB91_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -3988,7 +4663,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 ; VI-NEXT: v_mov_b32_e32 v1, s5 -; VI-NEXT: .LBB75_1: ; %atomicrmw.start +; VI-NEXT: .LBB91_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_max_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -3998,7 +4673,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB75_1 +; VI-NEXT: s_cbranch_execnz .LBB91_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -4016,7 +4691,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB75_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB91_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_max_i32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] offset:16 glc @@ -4026,7 +4701,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB75_1 +; GFX9-NEXT: s_cbranch_execnz .LBB91_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -4053,7 +4728,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB76_1: ; %atomicrmw.start +; SI-NEXT: .LBB92_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -4066,7 +4741,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB76_1 +; SI-NEXT: s_cbranch_execnz .LBB92_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -4094,7 +4769,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB76_1: ; %atomicrmw.start +; VI-NEXT: .LBB92_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_i32_e32 v2, s4, v3 @@ -4104,7 +4779,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB76_1 +; VI-NEXT: s_cbranch_execnz .LBB92_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -4127,7 +4802,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB76_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB92_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_i32_e32 v2, s2, v3 @@ -4137,7 +4812,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB76_1 +; GFX9-NEXT: s_cbranch_execnz .LBB92_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -4167,7 +4842,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB77_1: ; %atomicrmw.start +; SI-NEXT: .LBB93_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -4180,7 +4855,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB77_1 +; SI-NEXT: s_cbranch_execnz .LBB93_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -4199,7 +4874,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 -; VI-NEXT: .LBB77_1: ; %atomicrmw.start +; VI-NEXT: .LBB93_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_max_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -4209,7 +4884,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB77_1 +; VI-NEXT: s_cbranch_execnz .LBB93_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -4227,7 +4902,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB77_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB93_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_max_i32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc @@ -4237,7 +4912,7 @@ define amdgpu_kernel void @atomic_max_i32_addr64(ptr addrspace(1) %out, i32 %in, ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB77_1 +; GFX9-NEXT: s_cbranch_execnz .LBB93_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -4263,7 +4938,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB78_1: ; %atomicrmw.start +; SI-NEXT: .LBB94_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -4276,7 +4951,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB78_1 +; SI-NEXT: s_cbranch_execnz .LBB94_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -4302,7 +4977,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v1, s7 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB78_1: ; %atomicrmw.start +; VI-NEXT: .LBB94_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_i32_e32 v2, s4, v3 @@ -4312,7 +4987,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB78_1 +; VI-NEXT: s_cbranch_execnz .LBB94_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -4335,7 +5010,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB78_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB94_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_i32_e32 v2, s2, v3 @@ -4345,7 +5020,7 @@ define amdgpu_kernel void @atomic_max_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB78_1 +; GFX9-NEXT: s_cbranch_execnz .LBB94_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -4358,49 +5033,47 @@ entry: ret void } -; --------------------------------------------------------------------- -; atomicrmw umax -; --------------------------------------------------------------------- - -define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { -; SI-LABEL: global_atomic_umax_i32_noret: +define void @global_atomic_max_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_max_i32_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB79_1: ; %atomicrmw.start +; SI-NEXT: .LBB95_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_max_u32_e32 v3, v4, v2 +; SI-NEXT: v_max_i32_e32 v3, v4, v2 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: v_mov_b32_e32 v6, v4 ; SI-NEXT: v_mov_b32_e32 v5, v3 -; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB79_1 +; SI-NEXT: s_cbranch_execnz .LBB95_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_umax_i32_noret: +; VI-LABEL: global_atomic_max_i32_noret_offset__amdgpu_no_remote_memory_access: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB79_1: ; %atomicrmw.start +; VI-NEXT: .LBB95_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_max_u32_e32 v3, v4, v2 +; VI-NEXT: v_max_i32_e32 v3, v4, v2 ; VI-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: buffer_wbinvl1_vol @@ -4408,73 +5081,233 @@ define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB79_1 +; VI-NEXT: s_cbranch_execnz .LBB95_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: global_atomic_umax_i32_noret: +; GFX9-LABEL: global_atomic_max_i32_noret_offset__amdgpu_no_remote_memory_access: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: global_load_dword v4, v[0:1], off +; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB79_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB95_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) -; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 -; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX9-NEXT: v_max_i32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB79_1 +; GFX9-NEXT: s_cbranch_execnz .LBB95_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] - %tmp0 = atomicrmw umax ptr addrspace(1) %ptr, i32 %in seq_cst + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw max ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret void } -define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) { -; SI-LABEL: global_atomic_umax_i32_noret_offset: +define i32 @global_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB80_1: ; %atomicrmw.start +; SI-NEXT: .LBB96_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_max_u32_e32 v3, v4, v2 -; SI-NEXT: s_waitcnt expcnt(0) -; SI-NEXT: v_mov_b32_e32 v6, v4 ; SI-NEXT: v_mov_b32_e32 v5, v3 -; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_max_i32_e32 v4, v5, v2 +; SI-NEXT: v_mov_b32_e32 v3, v4 +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: buffer_atomic_cmpswap v[3:4], v[0:1], s[4:7], 0 addr64 offset:16 glc ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 -; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] -; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB80_1 +; SI-NEXT: s_cbranch_execnz .LBB96_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: v_mov_b32_e32 v0, v3 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_umax_i32_noret_offset: +; VI-LABEL: global_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 -; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[3:4] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB96_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, v0 +; VI-NEXT: v_max_i32_e32 v0, v1, v2 +; VI-NEXT: flat_atomic_cmpswap v0, v[3:4], v[0:1] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB96_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_max_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB96_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: v_max_i32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB96_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v3 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw max ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + +; --------------------------------------------------------------------- +; atomicrmw umax +; --------------------------------------------------------------------- + +define void @global_atomic_umax_i32_noret(ptr addrspace(1) %ptr, i32 %in) { +; SI-LABEL: global_atomic_umax_i32_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB97_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_max_u32_e32 v3, v4, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v4 +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB97_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i32_noret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: flat_load_dword v4, v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB97_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_max_u32_e32 v3, v4, v2 +; VI-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v4, v3 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB97_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umax_i32_noret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v4, v[0:1], off +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB97_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB97_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %tmp0 = atomicrmw umax ptr addrspace(1) %ptr, i32 %in seq_cst + ret void +} + +define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_umax_i32_noret_offset: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB98_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_max_u32_e32 v3, v4, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v4 +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB98_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i32_noret_offset: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB80_1: ; %atomicrmw.start +; VI-NEXT: .LBB98_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4485,7 +5318,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB80_1 +; VI-NEXT: s_cbranch_execnz .LBB98_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4495,7 +5328,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB80_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB98_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 @@ -4506,7 +5339,7 @@ define void @global_atomic_umax_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB80_1 +; GFX9-NEXT: s_cbranch_execnz .LBB98_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4525,7 +5358,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB81_1: ; %atomicrmw.start +; SI-NEXT: .LBB99_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -4539,7 +5372,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB81_1 +; SI-NEXT: s_cbranch_execnz .LBB99_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -4551,7 +5384,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB81_1: ; %atomicrmw.start +; VI-NEXT: .LBB99_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -4562,7 +5395,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB81_1 +; VI-NEXT: s_cbranch_execnz .LBB99_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -4573,7 +5406,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB81_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB99_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -4584,7 +5417,7 @@ define i32 @global_atomic_umax_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB81_1 +; GFX9-NEXT: s_cbranch_execnz .LBB99_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -4603,7 +5436,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB82_1: ; %atomicrmw.start +; SI-NEXT: .LBB100_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -4617,7 +5450,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB82_1 +; SI-NEXT: s_cbranch_execnz .LBB100_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -4631,7 +5464,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB82_1: ; %atomicrmw.start +; VI-NEXT: .LBB100_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -4642,7 +5475,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB82_1 +; VI-NEXT: s_cbranch_execnz .LBB100_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4652,7 +5485,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB82_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB100_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -4663,7 +5496,7 @@ define i32 @global_atomic_umax_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB82_1 +; GFX9-NEXT: s_cbranch_execnz .LBB100_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -4688,7 +5521,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB83_1: ; %atomicrmw.start +; SI-NEXT: .LBB101_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_u32_e32 v0, s34, v1 @@ -4702,7 +5535,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB83_1 +; SI-NEXT: s_cbranch_execnz .LBB101_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -4720,7 +5553,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB83_1: ; %atomicrmw.start +; VI-NEXT: .LBB101_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v2, s6, v3 @@ -4731,7 +5564,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB83_1 +; VI-NEXT: s_cbranch_execnz .LBB101_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4742,7 +5575,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB83_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB101_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v0, s6, v1 @@ -4753,7 +5586,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB83_1 +; GFX9-NEXT: s_cbranch_execnz .LBB101_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4776,7 +5609,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB84_1: ; %atomicrmw.start +; SI-NEXT: .LBB102_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_max_u32_e32 v0, s34, v1 @@ -4790,7 +5623,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB84_1 +; SI-NEXT: s_cbranch_execnz .LBB102_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -4810,7 +5643,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB84_1: ; %atomicrmw.start +; VI-NEXT: .LBB102_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_max_u32_e32 v2, s6, v3 @@ -4821,7 +5654,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB84_1 +; VI-NEXT: s_cbranch_execnz .LBB102_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4832,7 +5665,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB84_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB102_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_max_u32_e32 v0, s6, v1 @@ -4843,7 +5676,7 @@ define amdgpu_gfx void @global_atomic_umax_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB84_1 +; GFX9-NEXT: s_cbranch_execnz .LBB102_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4867,7 +5700,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB85_1: ; %atomicrmw.start +; SI-NEXT: .LBB103_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -4881,7 +5714,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB85_1 +; SI-NEXT: s_cbranch_execnz .LBB103_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -4901,7 +5734,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB85_1: ; %atomicrmw.start +; VI-NEXT: .LBB103_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -4912,7 +5745,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB85_1 +; VI-NEXT: s_cbranch_execnz .LBB103_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4923,7 +5756,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB85_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB103_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -4934,7 +5767,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB85_1 +; GFX9-NEXT: s_cbranch_execnz .LBB103_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4957,7 +5790,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB86_1: ; %atomicrmw.start +; SI-NEXT: .LBB104_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -4971,7 +5804,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB86_1 +; SI-NEXT: s_cbranch_execnz .LBB104_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -4991,7 +5824,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB86_1: ; %atomicrmw.start +; VI-NEXT: .LBB104_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -5002,7 +5835,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB86_1 +; VI-NEXT: s_cbranch_execnz .LBB104_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5013,7 +5846,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB86_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB104_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -5024,7 +5857,7 @@ define amdgpu_gfx i32 @global_atomic_umax_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB86_1 +; GFX9-NEXT: s_cbranch_execnz .LBB104_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5049,7 +5882,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB87_1: ; %atomicrmw.start +; SI-NEXT: .LBB105_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_u32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -5062,7 +5895,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB87_1 +; SI-NEXT: s_cbranch_execnz .LBB105_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -5083,7 +5916,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 ; VI-NEXT: v_mov_b32_e32 v1, s5 -; VI-NEXT: .LBB87_1: ; %atomicrmw.start +; VI-NEXT: .LBB105_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_max_u32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -5093,7 +5926,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB87_1 +; VI-NEXT: s_cbranch_execnz .LBB105_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -5111,7 +5944,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB87_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB105_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_max_u32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] offset:16 glc @@ -5121,7 +5954,7 @@ define amdgpu_kernel void @atomic_umax_i32_addr64_offset(ptr addrspace(1) %out, ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB87_1 +; GFX9-NEXT: s_cbranch_execnz .LBB105_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -5148,7 +5981,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB88_1: ; %atomicrmw.start +; SI-NEXT: .LBB106_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_u32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -5161,7 +5994,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB88_1 +; SI-NEXT: s_cbranch_execnz .LBB106_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -5189,7 +6022,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB88_1: ; %atomicrmw.start +; VI-NEXT: .LBB106_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_u32_e32 v2, s4, v3 @@ -5199,7 +6032,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB88_1 +; VI-NEXT: s_cbranch_execnz .LBB106_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -5222,7 +6055,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB88_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB106_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_u32_e32 v2, s2, v3 @@ -5232,7 +6065,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(ptr addrspace(1) %o ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB88_1 +; GFX9-NEXT: s_cbranch_execnz .LBB106_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -5263,7 +6096,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB89_1: ; %atomicrmw.start +; SI-NEXT: .LBB107_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_max_u32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -5276,7 +6109,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB89_1 +; SI-NEXT: s_cbranch_execnz .LBB107_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -5302,7 +6135,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v1, s7 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB89_1: ; %atomicrmw.start +; VI-NEXT: .LBB107_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_max_u32_e32 v2, s4, v3 @@ -5312,7 +6145,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB89_1 +; VI-NEXT: s_cbranch_execnz .LBB107_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -5335,7 +6168,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB89_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB107_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_max_u32_e32 v2, s2, v3 @@ -5345,7 +6178,7 @@ define amdgpu_kernel void @atomic_umax_i32_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB89_1 +; GFX9-NEXT: s_cbranch_execnz .LBB107_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -5358,6 +6191,164 @@ entry: ret void } +define void @global_atomic_umax_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_umax_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB108_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_max_u32_e32 v3, v4, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v4 +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB108_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v4, v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB108_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_max_u32_e32 v3, v4, v2 +; VI-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v4, v3 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB108_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umax_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB108_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB108_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw umax ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB109_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_max_u32_e32 v4, v5, v2 +; SI-NEXT: v_mov_b32_e32 v3, v4 +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: buffer_atomic_cmpswap v[3:4], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB109_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: v_mov_b32_e32 v0, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[3:4] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB109_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, v0 +; VI-NEXT: v_max_u32_e32 v0, v1, v2 +; VI-NEXT: flat_atomic_cmpswap v0, v[3:4], v[0:1] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB109_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umax_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB109_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: v_max_u32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB109_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v3 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw umax ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw umin ; --------------------------------------------------------------------- @@ -5372,7 +6363,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB90_1: ; %atomicrmw.start +; SI-NEXT: .LBB110_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5386,7 +6377,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB90_1 +; SI-NEXT: s_cbranch_execnz .LBB110_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5397,7 +6388,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB90_1: ; %atomicrmw.start +; VI-NEXT: .LBB110_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5408,7 +6399,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB90_1 +; VI-NEXT: s_cbranch_execnz .LBB110_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5418,7 +6409,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB90_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB110_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5429,7 +6420,7 @@ define void @global_atomic_umin_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB90_1 +; GFX9-NEXT: s_cbranch_execnz .LBB110_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5447,7 +6438,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB91_1: ; %atomicrmw.start +; SI-NEXT: .LBB111_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5461,7 +6452,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB91_1 +; SI-NEXT: s_cbranch_execnz .LBB111_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5474,7 +6465,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB91_1: ; %atomicrmw.start +; VI-NEXT: .LBB111_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5485,7 +6476,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB91_1 +; VI-NEXT: s_cbranch_execnz .LBB111_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5495,7 +6486,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB91_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB111_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v3, v4, v2 @@ -5506,7 +6497,7 @@ define void @global_atomic_umin_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB91_1 +; GFX9-NEXT: s_cbranch_execnz .LBB111_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5525,7 +6516,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB92_1: ; %atomicrmw.start +; SI-NEXT: .LBB112_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -5539,7 +6530,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB92_1 +; SI-NEXT: s_cbranch_execnz .LBB112_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -5551,7 +6542,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB92_1: ; %atomicrmw.start +; VI-NEXT: .LBB112_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -5562,7 +6553,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB92_1 +; VI-NEXT: s_cbranch_execnz .LBB112_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -5573,7 +6564,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB92_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB112_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -5584,7 +6575,7 @@ define i32 @global_atomic_umin_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB92_1 +; GFX9-NEXT: s_cbranch_execnz .LBB112_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -5603,7 +6594,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB93_1: ; %atomicrmw.start +; SI-NEXT: .LBB113_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -5617,7 +6608,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB93_1 +; SI-NEXT: s_cbranch_execnz .LBB113_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -5631,7 +6622,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB93_1: ; %atomicrmw.start +; VI-NEXT: .LBB113_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -5642,7 +6633,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB93_1 +; VI-NEXT: s_cbranch_execnz .LBB113_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5652,7 +6643,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB93_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB113_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -5663,7 +6654,7 @@ define i32 @global_atomic_umin_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB93_1 +; GFX9-NEXT: s_cbranch_execnz .LBB113_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -5688,7 +6679,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB94_1: ; %atomicrmw.start +; SI-NEXT: .LBB114_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v0, s34, v1 @@ -5702,7 +6693,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB94_1 +; SI-NEXT: s_cbranch_execnz .LBB114_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -5720,7 +6711,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB94_1: ; %atomicrmw.start +; VI-NEXT: .LBB114_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v2, s6, v3 @@ -5731,7 +6722,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB94_1 +; VI-NEXT: s_cbranch_execnz .LBB114_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5742,7 +6733,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB94_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB114_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v0, s6, v1 @@ -5753,7 +6744,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB94_1 +; GFX9-NEXT: s_cbranch_execnz .LBB114_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5776,7 +6767,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB95_1: ; %atomicrmw.start +; SI-NEXT: .LBB115_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_u32_e32 v0, s34, v1 @@ -5790,7 +6781,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB95_1 +; SI-NEXT: s_cbranch_execnz .LBB115_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -5810,7 +6801,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB95_1: ; %atomicrmw.start +; VI-NEXT: .LBB115_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_u32_e32 v2, s6, v3 @@ -5821,7 +6812,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB95_1 +; VI-NEXT: s_cbranch_execnz .LBB115_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5832,7 +6823,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB95_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB115_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_u32_e32 v0, s6, v1 @@ -5843,7 +6834,7 @@ define amdgpu_gfx void @global_atomic_umin_i32_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB95_1 +; GFX9-NEXT: s_cbranch_execnz .LBB115_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5867,7 +6858,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB96_1: ; %atomicrmw.start +; SI-NEXT: .LBB116_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -5881,7 +6872,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB96_1 +; SI-NEXT: s_cbranch_execnz .LBB116_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -5901,7 +6892,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB96_1: ; %atomicrmw.start +; VI-NEXT: .LBB116_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -5912,7 +6903,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB96_1 +; VI-NEXT: s_cbranch_execnz .LBB116_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5923,7 +6914,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB96_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB116_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -5934,7 +6925,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB96_1 +; GFX9-NEXT: s_cbranch_execnz .LBB116_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5957,7 +6948,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB97_1: ; %atomicrmw.start +; SI-NEXT: .LBB117_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -5971,7 +6962,7 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB97_1 +; SI-NEXT: s_cbranch_execnz .LBB117_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -5991,45 +6982,203 @@ define amdgpu_gfx i32 @global_atomic_umin_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB97_1: ; %atomicrmw.start +; VI-NEXT: .LBB117_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v4, v0 +; VI-NEXT: v_min_u32_e32 v3, s6, v4 +; VI-NEXT: flat_atomic_cmpswap v0, v[1:2], v[3:4] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 +; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] +; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] +; VI-NEXT: s_cbranch_execnz .LBB117_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[34:35] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umin_i32_ret_offset_scalar: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 +; GFX9-NEXT: s_mov_b64 s[34:35], 0 +; GFX9-NEXT: .LBB117_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_min_u32_e32 v2, s6, v3 +; GFX9-NEXT: global_atomic_cmpswap v0, v1, v[2:3], s[4:5] offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 +; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] +; GFX9-NEXT: s_cbranch_execnz .LBB117_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i32 4 + %result = atomicrmw umin ptr addrspace(1) %gep, i32 %in seq_cst + ret i32 %result +} + +define void @global_atomic_umin_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_umin_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB118_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_min_u32_e32 v3, v4, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v4 +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB118_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umin_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v4, v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB118_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_min_u32_e32 v3, v4, v2 +; VI-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v4, v3 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB118_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umin_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB118_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_min_u32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB118_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw umin ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB119_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_min_u32_e32 v4, v5, v2 +; SI-NEXT: v_mov_b32_e32 v3, v4 +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: buffer_atomic_cmpswap v[3:4], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB119_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: v_mov_b32_e32 v0, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[3:4] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB119_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_mov_b32_e32 v4, v0 -; VI-NEXT: v_min_u32_e32 v3, s6, v4 -; VI-NEXT: flat_atomic_cmpswap v0, v[1:2], v[3:4] glc +; VI-NEXT: v_mov_b32_e32 v1, v0 +; VI-NEXT: v_min_u32_e32 v0, v1, v2 +; VI-NEXT: flat_atomic_cmpswap v0, v[3:4], v[0:1] glc ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: buffer_wbinvl1_vol -; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 -; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB97_1 +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB119_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end -; VI-NEXT: s_or_b64 exec, exec, s[34:35] +; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: global_atomic_umin_i32_ret_offset_scalar: +; GFX9-LABEL: global_atomic_umin_i32_ret_offset__amdgpu_no_remote_memory_access: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v1, 0 -; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 -; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB97_1: ; %atomicrmw.start +; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB119_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v3, v0 -; GFX9-NEXT: v_min_u32_e32 v2, s6, v3 -; GFX9-NEXT: global_atomic_cmpswap v0, v1, v[2:3], s[4:5] offset:16 glc +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: v_min_u32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol -; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB97_1 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB119_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end -; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v3 ; GFX9-NEXT: s_setpc_b64 s[30:31] - %gep = getelementptr i32, ptr addrspace(1) %out, i32 4 - %result = atomicrmw umin ptr addrspace(1) %gep, i32 %in seq_cst + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw umin ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret i32 %result } @@ -6047,7 +7196,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB98_1: ; %atomicrmw.start +; SI-NEXT: .LBB120_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6061,7 +7210,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB98_1 +; SI-NEXT: s_cbranch_execnz .LBB120_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6072,7 +7221,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB98_1: ; %atomicrmw.start +; VI-NEXT: .LBB120_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6083,7 +7232,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB98_1 +; VI-NEXT: s_cbranch_execnz .LBB120_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6093,7 +7242,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB98_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB120_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6104,7 +7253,7 @@ define void @global_atomic_min_i32_noret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB98_1 +; GFX9-NEXT: s_cbranch_execnz .LBB120_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6122,7 +7271,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB99_1: ; %atomicrmw.start +; SI-NEXT: .LBB121_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6136,7 +7285,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: v_mov_b32_e32 v4, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB99_1 +; SI-NEXT: s_cbranch_execnz .LBB121_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6149,7 +7298,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v4, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB99_1: ; %atomicrmw.start +; VI-NEXT: .LBB121_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6160,7 +7309,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v4, v3 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB99_1 +; VI-NEXT: s_cbranch_execnz .LBB121_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6170,7 +7319,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB99_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB121_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v3, v4, v2 @@ -6181,7 +7330,7 @@ define void @global_atomic_min_i32_noret_offset(ptr addrspace(1) %out, i32 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v4, v3 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB99_1 +; GFX9-NEXT: s_cbranch_execnz .LBB121_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6200,7 +7349,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB100_1: ; %atomicrmw.start +; SI-NEXT: .LBB122_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -6214,7 +7363,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB100_1 +; SI-NEXT: s_cbranch_execnz .LBB122_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -6226,7 +7375,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB100_1: ; %atomicrmw.start +; VI-NEXT: .LBB122_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v3 @@ -6237,7 +7386,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB100_1 +; VI-NEXT: s_cbranch_execnz .LBB122_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v3 @@ -6248,7 +7397,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB100_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB122_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -6259,7 +7408,7 @@ define i32 @global_atomic_min_i32_ret(ptr addrspace(1) %ptr, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB100_1 +; GFX9-NEXT: s_cbranch_execnz .LBB122_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -6278,7 +7427,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB101_1: ; %atomicrmw.start +; SI-NEXT: .LBB123_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v3 @@ -6292,7 +7441,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB101_1 +; SI-NEXT: s_cbranch_execnz .LBB123_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: v_mov_b32_e32 v0, v3 @@ -6306,7 +7455,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dword v0, v[3:4] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB101_1: ; %atomicrmw.start +; VI-NEXT: .LBB123_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v1, v0 @@ -6317,7 +7466,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB101_1 +; VI-NEXT: s_cbranch_execnz .LBB123_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6327,7 +7476,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB101_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB123_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v4, v3 @@ -6338,7 +7487,7 @@ define i32 @global_atomic_min_i32_ret_offset(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB101_1 +; GFX9-NEXT: s_cbranch_execnz .LBB123_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v3 @@ -6363,7 +7512,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB102_1: ; %atomicrmw.start +; SI-NEXT: .LBB124_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v0, s34, v1 @@ -6377,7 +7526,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB102_1 +; SI-NEXT: s_cbranch_execnz .LBB124_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -6395,7 +7544,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB102_1: ; %atomicrmw.start +; VI-NEXT: .LBB124_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v2, s6, v3 @@ -6406,7 +7555,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB102_1 +; VI-NEXT: s_cbranch_execnz .LBB124_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6417,7 +7566,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB102_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB124_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v0, s6, v1 @@ -6428,7 +7577,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB102_1 +; GFX9-NEXT: s_cbranch_execnz .LBB124_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6451,7 +7600,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v1, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB103_1: ; %atomicrmw.start +; SI-NEXT: .LBB125_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_min_i32_e32 v0, s34, v1 @@ -6465,7 +7614,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB103_1 +; SI-NEXT: s_cbranch_execnz .LBB125_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v4, 1 @@ -6485,7 +7634,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: v_mov_b32_e32 v1, s35 ; VI-NEXT: flat_load_dword v3, v[0:1] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB103_1: ; %atomicrmw.start +; VI-NEXT: .LBB125_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_min_i32_e32 v2, s6, v3 @@ -6496,7 +7645,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB103_1 +; VI-NEXT: s_cbranch_execnz .LBB125_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6507,7 +7656,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dword v1, v2, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB103_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB125_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_min_i32_e32 v0, s6, v1 @@ -6518,7 +7667,7 @@ define amdgpu_gfx void @global_atomic_min_i32_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB103_1 +; GFX9-NEXT: s_cbranch_execnz .LBB125_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6542,7 +7691,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB104_1: ; %atomicrmw.start +; SI-NEXT: .LBB126_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -6556,7 +7705,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB104_1 +; SI-NEXT: s_cbranch_execnz .LBB126_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -6576,7 +7725,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_mov_b32_e32 v1, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB104_1: ; %atomicrmw.start +; VI-NEXT: .LBB126_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -6587,7 +7736,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB104_1 +; VI-NEXT: s_cbranch_execnz .LBB126_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6598,7 +7747,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB104_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB126_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -6609,7 +7758,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB104_1 +; GFX9-NEXT: s_cbranch_execnz .LBB126_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6632,7 +7781,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dword v0, off, s[4:7], 0 offset:16 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB105_1: ; %atomicrmw.start +; SI-NEXT: .LBB127_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v2, v0 @@ -6646,7 +7795,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB105_1 +; SI-NEXT: s_cbranch_execnz .LBB127_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v3, 1 @@ -6666,7 +7815,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v2, s35 ; VI-NEXT: flat_load_dword v0, v[1:2] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB105_1: ; %atomicrmw.start +; VI-NEXT: .LBB127_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v4, v0 @@ -6677,7 +7826,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v4 ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB105_1 +; VI-NEXT: s_cbranch_execnz .LBB127_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6688,7 +7837,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-NEXT: global_load_dword v0, v1, s[4:5] offset:16 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB105_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB127_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v3, v0 @@ -6699,7 +7848,7 @@ define amdgpu_gfx i32 @global_atomic_min_i32_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB105_1 +; GFX9-NEXT: s_cbranch_execnz .LBB127_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6724,7 +7873,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB106_1: ; %atomicrmw.start +; SI-NEXT: .LBB128_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6737,7 +7886,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB106_1 +; SI-NEXT: s_cbranch_execnz .LBB128_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -6758,7 +7907,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 ; VI-NEXT: v_mov_b32_e32 v1, s5 -; VI-NEXT: .LBB106_1: ; %atomicrmw.start +; VI-NEXT: .LBB128_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_min_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -6768,7 +7917,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB106_1 +; VI-NEXT: s_cbranch_execnz .LBB128_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -6786,7 +7935,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: .LBB106_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB128_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_min_i32_e32 v0, s2, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] offset:16 glc @@ -6796,7 +7945,7 @@ define amdgpu_kernel void @atomic_min_i32_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB106_1 +; GFX9-NEXT: s_cbranch_execnz .LBB128_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -6823,7 +7972,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s6 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB107_1: ; %atomicrmw.start +; SI-NEXT: .LBB129_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s8, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6836,7 +7985,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB107_1 +; SI-NEXT: s_cbranch_execnz .LBB129_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -6864,7 +8013,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s5 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB107_1: ; %atomicrmw.start +; VI-NEXT: .LBB129_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: v_min_i32_e32 v2, s4, v3 @@ -6874,7 +8023,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB107_1 +; VI-NEXT: s_cbranch_execnz .LBB129_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -6897,7 +8046,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: s_mov_b64 s[4:5], 0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB107_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB129_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v3, v0 ; GFX9-NEXT: v_min_i32_e32 v2, s2, v3 @@ -6907,7 +8056,7 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB107_1 +; GFX9-NEXT: s_cbranch_execnz .LBB129_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v1, 0 @@ -6933,7 +8082,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_mov_b32_e32 v1, s3 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB108_1: ; %atomicrmw.start +; SI-NEXT: .LBB130_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_min_i32_e32 v0, s2, v1 ; SI-NEXT: s_waitcnt expcnt(0) @@ -6946,7 +8095,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; SI-NEXT: v_mov_b32_e32 v1, v2 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB108_1 +; SI-NEXT: s_cbranch_execnz .LBB130_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -6961,7 +8110,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: v_mov_b32_e32 v1, s5 ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v3, s3 -; VI-NEXT: .LBB108_1: ; %atomicrmw.start +; VI-NEXT: .LBB130_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_min_i32_e32 v2, s2, v3 ; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc @@ -6971,7 +8120,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v3, v2 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB108_1 +; VI-NEXT: s_cbranch_execnz .LBB130_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -6985,7 +8134,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_load_dword s5, s[2:3], 0x0 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v1, s5 -; GFX9-NEXT: .LBB108_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB130_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_min_i32_e32 v0, s4, v1 ; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[2:3] glc @@ -6995,7 +8144,7 @@ define amdgpu_kernel void @atomic_min_i32(ptr addrspace(1) %out, i32 %in) { ; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; GFX9-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX9-NEXT: s_cbranch_execnz .LBB108_1 +; GFX9-NEXT: s_cbranch_execnz .LBB130_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -7017,102 +8166,260 @@ define amdgpu_kernel void @atomic_min_i32_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: s_load_dword s6, s[4:5], 0x0 ; SI-NEXT: s_mov_b64 s[0:1], 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 -; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_mov_b32_e32 v1, s6 -; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB109_1: ; %atomicrmw.start +; SI-NEXT: s_waitcnt lgkmcnt(0) +; SI-NEXT: v_mov_b32_e32 v1, s6 +; SI-NEXT: s_mov_b32 s6, -1 +; SI-NEXT: .LBB131_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: v_min_i32_e32 v0, s8, v1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v3, v1 +; SI-NEXT: v_mov_b32_e32 v2, v0 +; SI-NEXT: buffer_atomic_cmpswap v[2:3], off, s[4:7], 0 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; SI-NEXT: v_mov_b32_e32 v1, v2 +; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] +; SI-NEXT: s_cbranch_execnz .LBB131_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[0:1] +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s6, -1 +; SI-NEXT: s_mov_b32 s4, s2 +; SI-NEXT: s_mov_b32 s5, s3 +; SI-NEXT: buffer_store_dword v2, off, s[4:7], 0 +; SI-NEXT: s_endpgm +; +; VI-LABEL: atomic_min_i32_ret_addr64: +; VI: ; %bb.0: ; %entry +; VI-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x34 +; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_ashr_i32 s7, s5, 31 +; VI-NEXT: s_mov_b32 s6, s5 +; VI-NEXT: s_lshl_b64 s[6:7], s[6:7], 2 +; VI-NEXT: s_add_u32 s6, s0, s6 +; VI-NEXT: s_addc_u32 s7, s1, s7 +; VI-NEXT: s_load_dword s5, s[6:7], 0x0 +; VI-NEXT: v_mov_b32_e32 v0, s6 +; VI-NEXT: s_mov_b64 s[0:1], 0 +; VI-NEXT: v_mov_b32_e32 v1, s7 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v2, s5 +; VI-NEXT: .LBB131_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: v_mov_b32_e32 v3, v2 +; VI-NEXT: v_min_i32_e32 v2, s4, v3 +; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 +; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] +; VI-NEXT: s_cbranch_execnz .LBB131_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[0:1] +; VI-NEXT: v_mov_b32_e32 v0, s2 +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: flat_store_dword v[0:1], v2 +; VI-NEXT: s_endpgm +; +; GFX9-LABEL: atomic_min_i32_ret_addr64: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x34 +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_ashr_i32 s1, s3, 31 +; GFX9-NEXT: s_mov_b32 s0, s3 +; GFX9-NEXT: s_lshl_b64 s[0:1], s[0:1], 2 +; GFX9-NEXT: s_add_u32 s0, s4, s0 +; GFX9-NEXT: s_addc_u32 s1, s5, s1 +; GFX9-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: .LBB131_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_mov_b32_e32 v3, v0 +; GFX9-NEXT: v_min_i32_e32 v2, s2, v3 +; GFX9-NEXT: global_atomic_cmpswap v0, v1, v[2:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB131_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: global_store_dword v1, v0, s[6:7] +; GFX9-NEXT: s_endpgm +entry: + %ptr = getelementptr i32, ptr addrspace(1) %out, i32 %index + %tmp0 = atomicrmw min ptr addrspace(1) %ptr, i32 %in seq_cst + store i32 %tmp0, ptr addrspace(1) %out2 + ret void +} + +define void @global_atomic_min_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_min_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v4, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB132_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_min_i32_e32 v3, v4, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v4 +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: buffer_atomic_cmpswap v[5:6], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v5, v4 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB132_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_min_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v4, v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB132_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_min_i32_e32 v3, v4, v2 +; VI-NEXT: flat_atomic_cmpswap v3, v[0:1], v[3:4] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v4, v3 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB132_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_min_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v4, v[0:1], off offset:16 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB132_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_min_i32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB132_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw min ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dword v3, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB133_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 -; SI-NEXT: v_min_i32_e32 v0, s8, v1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 ; SI-NEXT: s_waitcnt expcnt(0) -; SI-NEXT: v_mov_b32_e32 v3, v1 -; SI-NEXT: v_mov_b32_e32 v2, v0 -; SI-NEXT: buffer_atomic_cmpswap v[2:3], off, s[4:7], 0 glc +; SI-NEXT: v_min_i32_e32 v4, v5, v2 +; SI-NEXT: v_mov_b32_e32 v3, v4 +; SI-NEXT: v_mov_b32_e32 v4, v5 +; SI-NEXT: buffer_atomic_cmpswap v[3:4], v[0:1], s[4:7], 0 addr64 offset:16 glc ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 -; SI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 -; SI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; SI-NEXT: v_mov_b32_e32 v1, v2 -; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB109_1 +; SI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v5 +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB133_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end -; SI-NEXT: s_or_b64 exec, exec, s[0:1] -; SI-NEXT: s_mov_b32 s7, 0xf000 -; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: s_mov_b32 s4, s2 -; SI-NEXT: s_mov_b32 s5, s3 -; SI-NEXT: buffer_store_dword v2, off, s[4:7], 0 -; SI-NEXT: s_endpgm +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: v_mov_b32_e32 v0, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: atomic_min_i32_ret_addr64: -; VI: ; %bb.0: ; %entry -; VI-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x34 -; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 -; VI-NEXT: s_waitcnt lgkmcnt(0) -; VI-NEXT: s_ashr_i32 s7, s5, 31 -; VI-NEXT: s_mov_b32 s6, s5 -; VI-NEXT: s_lshl_b64 s[6:7], s[6:7], 2 -; VI-NEXT: s_add_u32 s6, s0, s6 -; VI-NEXT: s_addc_u32 s7, s1, s7 -; VI-NEXT: s_load_dword s5, s[6:7], 0x0 -; VI-NEXT: v_mov_b32_e32 v0, s6 -; VI-NEXT: s_mov_b64 s[0:1], 0 -; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: s_waitcnt lgkmcnt(0) -; VI-NEXT: v_mov_b32_e32 v2, s5 -; VI-NEXT: .LBB109_1: ; %atomicrmw.start +; VI-LABEL: global_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v3, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v4, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[3:4] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB133_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 -; VI-NEXT: v_mov_b32_e32 v3, v2 -; VI-NEXT: v_min_i32_e32 v2, s4, v3 -; VI-NEXT: flat_atomic_cmpswap v2, v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, v0 +; VI-NEXT: v_min_i32_e32 v0, v1, v2 +; VI-NEXT: flat_atomic_cmpswap v0, v[3:4], v[0:1] glc ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: buffer_wbinvl1_vol -; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 -; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB109_1 +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB133_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end -; VI-NEXT: s_or_b64 exec, exec, s[0:1] -; VI-NEXT: v_mov_b32_e32 v0, s2 -; VI-NEXT: v_mov_b32_e32 v1, s3 -; VI-NEXT: flat_store_dword v[0:1], v2 -; VI-NEXT: s_endpgm +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: atomic_min_i32_ret_addr64: -; GFX9: ; %bb.0: ; %entry -; GFX9-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x34 -; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 -; GFX9-NEXT: v_mov_b32_e32 v1, 0 -; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: s_ashr_i32 s1, s3, 31 -; GFX9-NEXT: s_mov_b32 s0, s3 -; GFX9-NEXT: s_lshl_b64 s[0:1], s[0:1], 2 -; GFX9-NEXT: s_add_u32 s0, s4, s0 -; GFX9-NEXT: s_addc_u32 s1, s5, s1 -; GFX9-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX9-LABEL: global_atomic_min_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dword v3, v[0:1], off offset:16 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v0, s3 -; GFX9-NEXT: .LBB109_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB133_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX9-NEXT: v_mov_b32_e32 v3, v0 -; GFX9-NEXT: v_min_i32_e32 v2, s2, v3 -; GFX9-NEXT: global_atomic_cmpswap v0, v1, v[2:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v4, v3 +; GFX9-NEXT: v_min_i32_e32 v3, v4, v2 +; GFX9-NEXT: global_atomic_cmpswap v3, v[0:1], v[3:4], off offset:16 glc ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol -; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v4 ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB109_1 +; GFX9-NEXT: s_cbranch_execnz .LBB133_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] -; GFX9-NEXT: v_mov_b32_e32 v1, 0 -; GFX9-NEXT: global_store_dword v1, v0, s[6:7] -; GFX9-NEXT: s_endpgm -entry: - %ptr = getelementptr i32, ptr addrspace(1) %out, i32 %index - %tmp0 = atomicrmw min ptr addrspace(1) %ptr, i32 %in seq_cst - store i32 %tmp0, ptr addrspace(1) %out2 - ret void +; GFX9-NEXT: v_mov_b32_e32 v0, v3 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw min ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result } ; --------------------------------------------------------------------- @@ -7465,6 +8772,79 @@ define amdgpu_gfx i32 @global_atomic_uinc_wrap_i32_ret_offset_scalar(ptr addrspa ret i32 %result } +define void @global_atomic_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_inc v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_inc v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_uinc_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_inc v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw uinc_wrap ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_inc v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_inc v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_uinc_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_inc v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw uinc_wrap ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + ; --------------------------------------------------------------------- ; atomicrmw udec_wrap ; --------------------------------------------------------------------- @@ -7814,3 +9194,78 @@ define amdgpu_gfx i32 @global_atomic_udec_wrap_i32_ret_offset_scalar(ptr addrspa %result = atomicrmw udec_wrap ptr addrspace(1) %gep, i32 %in seq_cst ret i32 %result } + +define void @global_atomic_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_dec v2, v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_dec v[0:1], v2 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_udec_wrap_i32_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_dec v[0:1], v2, off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw udec_wrap ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i32 @global_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i32 %in) { +; SI-LABEL: global_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_dec v2, v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_dec v0, v[0:1], v2 glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_udec_wrap_i32_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_dec v0, v[0:1], v2, off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw udec_wrap ptr addrspace(1) %gep, i32 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %result +} + +!0 = !{} diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll index 380ce7f3b939..f5c2bd6286cb 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll @@ -367,6 +367,80 @@ define amdgpu_gfx i64 @global_atomic_xchg_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } +define void @global_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw xchg ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw xchg ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw xchg f64 ; --------------------------------------------------------------------- @@ -731,6 +805,80 @@ define amdgpu_gfx double @global_atomic_xchg_f64_ret_offset_scalar(ptr addrspace ret double %result } +define void @global_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, double %in) { +; SI-LABEL: global_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:16 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_f64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap_x2 v[0:1], v[2:3], off offset:16 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw xchg ptr addrspace(1) %gep, double %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define double @global_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, double %in) { +; SI-LABEL: global_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_swap_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:16 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 16, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_swap_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xchg_f64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_swap_x2 v[0:1], v[0:1], v[2:3], off offset:16 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i32, ptr addrspace(1) %out, i64 4 + %result = atomicrmw xchg ptr addrspace(1) %gep, double %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %result +} + ; --------------------------------------------------------------------- ; atomicrmw add ; --------------------------------------------------------------------- @@ -1095,6 +1243,80 @@ define amdgpu_gfx i64 @global_atomic_add_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } +define void @global_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_add_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_add_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_add_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw add ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_add_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_add_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_add_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_add_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw add ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw sub ; --------------------------------------------------------------------- @@ -1459,6 +1681,80 @@ define amdgpu_gfx i64 @global_atomic_sub_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } +define void @global_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_sub_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_sub_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_sub_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_sub_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw sub ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_sub_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_sub_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_sub_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_sub_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw sub ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw and ; --------------------------------------------------------------------- @@ -1823,21 +2119,95 @@ define amdgpu_gfx i64 @global_atomic_and_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } -; --------------------------------------------------------------------- -; atomicrmw nand -; --------------------------------------------------------------------- - -define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { -; SI-LABEL: global_atomic_nand_i64_noret: +define void @global_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 -; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB40_1: ; %atomicrmw.start +; SI-NEXT: buffer_atomic_and_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_and_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_and_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_and_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw and ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_and_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_and_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_and_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_and_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw and ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw nand +; --------------------------------------------------------------------- + +define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { +; SI-LABEL: global_atomic_nand_i64_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB50_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1857,7 +2227,7 @@ define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB40_1 +; SI-NEXT: s_cbranch_execnz .LBB50_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -1868,7 +2238,7 @@ define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB40_1: ; %atomicrmw.start +; VI-NEXT: .LBB50_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1883,7 +2253,7 @@ define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB40_1 +; VI-NEXT: s_cbranch_execnz .LBB50_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -1893,7 +2263,7 @@ define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB40_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB50_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1908,7 +2278,7 @@ define void @global_atomic_nand_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB40_1 +; GFX9-NEXT: s_cbranch_execnz .LBB50_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -1926,7 +2296,7 @@ define void @global_atomic_nand_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB41_1: ; %atomicrmw.start +; SI-NEXT: .LBB51_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1946,7 +2316,7 @@ define void @global_atomic_nand_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB41_1 +; SI-NEXT: s_cbranch_execnz .LBB51_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -1959,7 +2329,7 @@ define void @global_atomic_nand_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB41_1: ; %atomicrmw.start +; VI-NEXT: .LBB51_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1974,7 +2344,7 @@ define void @global_atomic_nand_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB41_1 +; VI-NEXT: s_cbranch_execnz .LBB51_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -1984,7 +2354,7 @@ define void @global_atomic_nand_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB41_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB51_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v4, v7, v3 @@ -1999,7 +2369,7 @@ define void @global_atomic_nand_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB41_1 +; GFX9-NEXT: s_cbranch_execnz .LBB51_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2022,7 +2392,7 @@ define i64 @global_atomic_nand_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[4:5], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB42_1: ; %atomicrmw.start +; SI-NEXT: .LBB52_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -2042,7 +2412,7 @@ define i64 @global_atomic_nand_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB42_1 +; SI-NEXT: s_cbranch_execnz .LBB52_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -2053,7 +2423,7 @@ define i64 @global_atomic_nand_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB42_1: ; %atomicrmw.start +; VI-NEXT: .LBB52_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v5 @@ -2068,7 +2438,7 @@ define i64 @global_atomic_nand_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB42_1 +; VI-NEXT: s_cbranch_execnz .LBB52_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v4 @@ -2080,7 +2450,7 @@ define i64 @global_atomic_nand_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB42_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB52_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -2095,7 +2465,7 @@ define i64 @global_atomic_nand_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB42_1 +; GFX9-NEXT: s_cbranch_execnz .LBB52_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -2119,7 +2489,7 @@ define i64 @global_atomic_nand_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[4:5], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB43_1: ; %atomicrmw.start +; SI-NEXT: .LBB53_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -2139,7 +2509,7 @@ define i64 @global_atomic_nand_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB43_1 +; SI-NEXT: s_cbranch_execnz .LBB53_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -2152,7 +2522,7 @@ define i64 @global_atomic_nand_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB43_1: ; %atomicrmw.start +; VI-NEXT: .LBB53_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -2167,7 +2537,7 @@ define i64 @global_atomic_nand_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB43_1 +; VI-NEXT: s_cbranch_execnz .LBB53_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2177,7 +2547,7 @@ define i64 @global_atomic_nand_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB43_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB53_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -2192,7 +2562,7 @@ define i64 @global_atomic_nand_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB43_1 +; GFX9-NEXT: s_cbranch_execnz .LBB53_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -2219,7 +2589,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dwordx2 v[2:3], off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB44_1: ; %atomicrmw.start +; SI-NEXT: .LBB54_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v0, s34, v3 @@ -2239,7 +2609,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB44_1 +; SI-NEXT: s_cbranch_execnz .LBB54_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v8, 1 @@ -2259,7 +2629,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v4, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v5, s5 -; VI-NEXT: .LBB44_1: ; %atomicrmw.start +; VI-NEXT: .LBB54_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v0, s7, v3 @@ -2274,7 +2644,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB44_1 +; VI-NEXT: s_cbranch_execnz .LBB54_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2285,7 +2655,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: v_mov_b32_e32 v4, 0 ; GFX9-NEXT: global_load_dwordx2 v[2:3], v4, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB44_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB54_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v0, s7, v3 @@ -2300,7 +2670,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB44_1 +; GFX9-NEXT: s_cbranch_execnz .LBB54_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2324,7 +2694,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dwordx2 v[2:3], off, s[4:7], 0 offset:32 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB45_1: ; %atomicrmw.start +; SI-NEXT: .LBB55_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_and_b32_e32 v0, s34, v3 @@ -2344,7 +2714,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_offset_scalar(ptr addrspace ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB45_1 +; SI-NEXT: s_cbranch_execnz .LBB55_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v8, 1 @@ -2364,7 +2734,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_offset_scalar(ptr addrspace ; VI-NEXT: v_mov_b32_e32 v5, s35 ; VI-NEXT: flat_load_dwordx2 v[2:3], v[4:5] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB45_1: ; %atomicrmw.start +; VI-NEXT: .LBB55_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_and_b32_e32 v0, s7, v3 @@ -2379,7 +2749,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB45_1 +; VI-NEXT: s_cbranch_execnz .LBB55_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2390,7 +2760,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: v_mov_b32_e32 v4, 0 ; GFX9-NEXT: global_load_dwordx2 v[2:3], v4, s[4:5] offset:32 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB45_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB55_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v0, s7, v3 @@ -2405,7 +2775,7 @@ define amdgpu_gfx void @global_atomic_nand_i64_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB45_1 +; GFX9-NEXT: s_cbranch_execnz .LBB55_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2430,7 +2800,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dwordx2 v[0:1], off, s[4:7], 0 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB46_1: ; %atomicrmw.start +; SI-NEXT: .LBB56_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v1 @@ -2450,7 +2820,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[4:5] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB46_1 +; SI-NEXT: s_cbranch_execnz .LBB56_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v6, 1 @@ -2470,7 +2840,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v2, s4 ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v3, s5 -; VI-NEXT: .LBB46_1: ; %atomicrmw.start +; VI-NEXT: .LBB56_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v1 @@ -2485,7 +2855,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB46_1 +; VI-NEXT: s_cbranch_execnz .LBB56_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2496,7 +2866,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dwordx2 v[0:1], v2, s[4:5] ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB46_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB56_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v6, v1 @@ -2511,7 +2881,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[5:6] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB46_1 +; GFX9-NEXT: s_cbranch_execnz .LBB56_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2535,7 +2905,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: buffer_load_dwordx2 v[0:1], off, s[4:7], 0 offset:32 ; SI-NEXT: s_mov_b64 s[36:37], 0 -; SI-NEXT: .LBB47_1: ; %atomicrmw.start +; SI-NEXT: .LBB57_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v5, v1 @@ -2555,7 +2925,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[4:5] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB47_1 +; SI-NEXT: s_cbranch_execnz .LBB57_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v6, 1 @@ -2575,7 +2945,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_mov_b32_e32 v3, s35 ; VI-NEXT: flat_load_dwordx2 v[0:1], v[2:3] ; VI-NEXT: s_mov_b64 s[34:35], 0 -; VI-NEXT: .LBB47_1: ; %atomicrmw.start +; VI-NEXT: .LBB57_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v1 @@ -2590,7 +2960,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[6:7] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB47_1 +; VI-NEXT: s_cbranch_execnz .LBB57_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -2601,7 +2971,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_mov_b32_e32 v2, 0 ; GFX9-NEXT: global_load_dwordx2 v[0:1], v2, s[4:5] offset:32 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: .LBB47_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB57_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v6, v1 @@ -2616,7 +2986,7 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[5:6] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB47_1 +; GFX9-NEXT: s_cbranch_execnz .LBB57_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -2625,6 +2995,196 @@ define amdgpu_gfx i64 @global_atomic_nand_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } +define void @global_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB58_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_and_b32_e32 v4, v7, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_and_b32_e32 v8, v6, v2 +; SI-NEXT: v_not_b32_e32 v5, v4 +; SI-NEXT: v_not_b32_e32 v4, v8 +; SI-NEXT: v_mov_b32_e32 v11, v7 +; SI-NEXT: v_mov_b32_e32 v10, v6 +; SI-NEXT: v_mov_b32_e32 v9, v5 +; SI-NEXT: v_mov_b32_e32 v8, v4 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v6, v8 +; SI-NEXT: v_mov_b32_e32 v7, v9 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB58_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB58_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_and_b32_e32 v4, v7, v3 +; VI-NEXT: v_and_b32_e32 v8, v6, v2 +; VI-NEXT: v_not_b32_e32 v5, v4 +; VI-NEXT: v_not_b32_e32 v4, v8 +; VI-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; VI-NEXT: v_mov_b32_e32 v7, v5 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v6, v4 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB58_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_nand_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB58_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_and_b32_e32 v4, v7, v3 +; GFX9-NEXT: v_and_b32_e32 v8, v6, v2 +; GFX9-NEXT: v_not_b32_e32 v5, v4 +; GFX9-NEXT: v_not_b32_e32 v4, v8 +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB58_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw nand ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: v_mov_b32_e32 v6, v3 +; SI-NEXT: v_mov_b32_e32 v7, v2 +; SI-NEXT: v_mov_b32_e32 v5, v1 +; SI-NEXT: v_mov_b32_e32 v4, v0 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[0:1], v[4:5], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB59_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v1 +; SI-NEXT: v_mov_b32_e32 v10, v0 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_and_b32_e32 v0, v11, v6 +; SI-NEXT: v_and_b32_e32 v1, v10, v7 +; SI-NEXT: v_not_b32_e32 v9, v0 +; SI-NEXT: v_not_b32_e32 v8, v1 +; SI-NEXT: v_mov_b32_e32 v0, v8 +; SI-NEXT: v_mov_b32_e32 v1, v9 +; SI-NEXT: v_mov_b32_e32 v2, v10 +; SI-NEXT: v_mov_b32_e32 v3, v11 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[0:3], v[4:5], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB59_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB59_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v9, v1 +; VI-NEXT: v_mov_b32_e32 v8, v0 +; VI-NEXT: v_and_b32_e32 v0, v9, v3 +; VI-NEXT: v_and_b32_e32 v1, v8, v2 +; VI-NEXT: v_not_b32_e32 v7, v0 +; VI-NEXT: v_not_b32_e32 v6, v1 +; VI-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB59_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_nand_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB59_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: v_and_b32_e32 v4, v7, v3 +; GFX9-NEXT: v_and_b32_e32 v8, v6, v2 +; GFX9-NEXT: v_not_b32_e32 v5, v4 +; GFX9-NEXT: v_not_b32_e32 v4, v8 +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB59_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v4 +; GFX9-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw nand ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw or ; --------------------------------------------------------------------- @@ -2989,36 +3549,110 @@ define amdgpu_gfx i64 @global_atomic_or_i64_ret_offset_scalar(ptr addrspace(1) i ret i64 %result } -; --------------------------------------------------------------------- -; atomicrmw xor -; --------------------------------------------------------------------- - -define void @global_atomic_xor_i64_noret(ptr addrspace(1) %ptr, i64 %in) { -; SI-LABEL: global_atomic_xor_i64_noret: +define void @global_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_atomic_xor_x2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: buffer_atomic_or_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_xor_i64_noret: +; VI-LABEL: global_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; VI-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_or_x2 v[0:1], v[2:3] ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: buffer_wbinvl1_vol ; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: global_atomic_xor_i64_noret: +; GFX9-LABEL: global_atomic_or_i64_noret_offset__amdgpu_no_remote_memory_access: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: global_atomic_xor_x2 v[0:1], v[2:3], off +; GFX9-NEXT: global_atomic_or_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw or ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_or_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_or_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_or_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_or_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw or ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw xor +; --------------------------------------------------------------------- + +define void @global_atomic_xor_i64_noret(ptr addrspace(1) %ptr, i64 %in) { +; SI-LABEL: global_atomic_xor_i64_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor_x2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i64_noret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i64_noret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor_x2 v[0:1], v[2:3], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3353,6 +3987,80 @@ define amdgpu_gfx i64 @global_atomic_xor_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } +define void @global_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_xor_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw xor ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_xor_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_xor_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_xor_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_xor_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw xor ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw max ; --------------------------------------------------------------------- @@ -3367,7 +4075,7 @@ define void @global_atomic_max_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB64_1: ; %atomicrmw.start +; SI-NEXT: .LBB80_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3386,7 +4094,7 @@ define void @global_atomic_max_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB64_1 +; SI-NEXT: s_cbranch_execnz .LBB80_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3397,7 +4105,7 @@ define void @global_atomic_max_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB64_1: ; %atomicrmw.start +; VI-NEXT: .LBB80_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3411,7 +4119,7 @@ define void @global_atomic_max_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB64_1 +; VI-NEXT: s_cbranch_execnz .LBB80_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3421,7 +4129,7 @@ define void @global_atomic_max_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB64_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB80_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3435,7 +4143,7 @@ define void @global_atomic_max_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB64_1 +; GFX9-NEXT: s_cbranch_execnz .LBB80_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3453,7 +4161,7 @@ define void @global_atomic_max_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB65_1: ; %atomicrmw.start +; SI-NEXT: .LBB81_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3472,7 +4180,7 @@ define void @global_atomic_max_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB65_1 +; SI-NEXT: s_cbranch_execnz .LBB81_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3485,7 +4193,7 @@ define void @global_atomic_max_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB65_1: ; %atomicrmw.start +; VI-NEXT: .LBB81_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3499,7 +4207,7 @@ define void @global_atomic_max_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB65_1 +; VI-NEXT: s_cbranch_execnz .LBB81_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3509,7 +4217,7 @@ define void @global_atomic_max_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB65_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB81_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] @@ -3523,7 +4231,7 @@ define void @global_atomic_max_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB65_1 +; GFX9-NEXT: s_cbranch_execnz .LBB81_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3546,7 +4254,7 @@ define i64 @global_atomic_max_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB66_1: ; %atomicrmw.start +; SI-NEXT: .LBB82_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -3565,7 +4273,7 @@ define i64 @global_atomic_max_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB66_1 +; SI-NEXT: s_cbranch_execnz .LBB82_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3576,7 +4284,7 @@ define i64 @global_atomic_max_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB66_1: ; %atomicrmw.start +; VI-NEXT: .LBB82_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v5 @@ -3590,7 +4298,7 @@ define i64 @global_atomic_max_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB66_1 +; VI-NEXT: s_cbranch_execnz .LBB82_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v4 @@ -3602,7 +4310,7 @@ define i64 @global_atomic_max_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB66_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB82_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -3616,7 +4324,7 @@ define i64 @global_atomic_max_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB66_1 +; GFX9-NEXT: s_cbranch_execnz .LBB82_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -3640,7 +4348,7 @@ define i64 @global_atomic_max_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB67_1: ; %atomicrmw.start +; SI-NEXT: .LBB83_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -3659,7 +4367,7 @@ define i64 @global_atomic_max_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB67_1 +; SI-NEXT: s_cbranch_execnz .LBB83_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -3672,7 +4380,7 @@ define i64 @global_atomic_max_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB67_1: ; %atomicrmw.start +; VI-NEXT: .LBB83_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -3686,7 +4394,7 @@ define i64 @global_atomic_max_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB67_1 +; VI-NEXT: s_cbranch_execnz .LBB83_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3696,7 +4404,7 @@ define i64 @global_atomic_max_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB67_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB83_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -3710,7 +4418,7 @@ define i64 @global_atomic_max_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB67_1 +; GFX9-NEXT: s_cbranch_execnz .LBB83_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -3739,7 +4447,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB68_1: ; %atomicrmw.start +; SI-NEXT: .LBB84_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_lt_i64_e32 vcc, s[34:35], v[2:3] @@ -3758,7 +4466,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB68_1 +; SI-NEXT: s_cbranch_execnz .LBB84_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -3780,7 +4488,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 ; VI-NEXT: v_mov_b32_e32 v5, s5 -; VI-NEXT: .LBB68_1: ; %atomicrmw.start +; VI-NEXT: .LBB84_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3794,7 +4502,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB68_1 +; VI-NEXT: s_cbranch_execnz .LBB84_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3807,7 +4515,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB68_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB84_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3821,7 +4529,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB68_1 +; GFX9-NEXT: s_cbranch_execnz .LBB84_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3847,7 +4555,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB69_1: ; %atomicrmw.start +; SI-NEXT: .LBB85_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_lt_i64_e32 vcc, s[34:35], v[2:3] @@ -3866,7 +4574,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_offset_scalar(ptr addrspace( ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB69_1 +; SI-NEXT: s_cbranch_execnz .LBB85_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -3888,7 +4596,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 -; VI-NEXT: .LBB69_1: ; %atomicrmw.start +; VI-NEXT: .LBB85_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3902,7 +4610,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB69_1 +; VI-NEXT: s_cbranch_execnz .LBB85_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -3915,7 +4623,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB69_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB85_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] @@ -3929,7 +4637,7 @@ define amdgpu_gfx void @global_atomic_max_i64_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB69_1 +; GFX9-NEXT: s_cbranch_execnz .LBB85_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -3956,7 +4664,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB70_1: ; %atomicrmw.start +; SI-NEXT: .LBB86_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -3975,7 +4683,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB70_1 +; SI-NEXT: s_cbranch_execnz .LBB86_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -3997,7 +4705,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 ; VI-NEXT: v_mov_b32_e32 v3, s5 -; VI-NEXT: .LBB70_1: ; %atomicrmw.start +; VI-NEXT: .LBB86_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -4011,7 +4719,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB70_1 +; VI-NEXT: s_cbranch_execnz .LBB86_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4024,7 +4732,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB70_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB86_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -4038,7 +4746,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB70_1 +; GFX9-NEXT: s_cbranch_execnz .LBB86_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4064,7 +4772,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB71_1: ; %atomicrmw.start +; SI-NEXT: .LBB87_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -4083,7 +4791,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB71_1 +; SI-NEXT: s_cbranch_execnz .LBB87_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -4105,7 +4813,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 -; VI-NEXT: .LBB71_1: ; %atomicrmw.start +; VI-NEXT: .LBB87_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -4119,7 +4827,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB71_1 +; VI-NEXT: s_cbranch_execnz .LBB87_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4132,7 +4840,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB71_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB87_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -4146,7 +4854,7 @@ define amdgpu_gfx i64 @global_atomic_max_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB71_1 +; GFX9-NEXT: s_cbranch_execnz .LBB87_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4173,7 +4881,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: v_mov_b32_e32 v2, s8 ; SI-NEXT: v_mov_b32_e32 v3, s9 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB72_1: ; %atomicrmw.start +; SI-NEXT: .LBB88_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -4191,7 +4899,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB72_1 +; SI-NEXT: s_cbranch_execnz .LBB88_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -4214,7 +4922,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: v_mov_b32_e32 v7, s2 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v4, s0 -; VI-NEXT: .LBB72_1: ; %atomicrmw.start +; VI-NEXT: .LBB88_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] ; VI-NEXT: v_cndmask_b32_e32 v1, v6, v3, vcc @@ -4227,7 +4935,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB72_1 +; VI-NEXT: s_cbranch_execnz .LBB88_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -4247,7 +4955,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v2, s4 ; GFX9-NEXT: v_mov_b32_e32 v3, s5 -; GFX9-NEXT: .LBB72_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB88_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] ; GFX9-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -4260,7 +4968,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX9-NEXT: s_cbranch_execnz .LBB72_1 +; GFX9-NEXT: s_cbranch_execnz .LBB88_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -4287,7 +4995,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: v_mov_b32_e32 v2, s6 ; SI-NEXT: v_mov_b32_e32 v3, s7 ; SI-NEXT: s_mov_b32 s10, -1 -; SI-NEXT: .LBB73_1: ; %atomicrmw.start +; SI-NEXT: .LBB89_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v8, v3, vcc @@ -4305,7 +5013,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB73_1 +; SI-NEXT: s_cbranch_execnz .LBB89_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -4333,7 +5041,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_mov_b32_e32 v5, s4 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v1, s1 -; VI-NEXT: .LBB73_1: ; %atomicrmw.start +; VI-NEXT: .LBB89_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v9, v3 ; VI-NEXT: v_mov_b32_e32 v8, v2 @@ -4346,7 +5054,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; VI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; VI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; VI-NEXT: s_cbranch_execnz .LBB73_1 +; VI-NEXT: s_cbranch_execnz .LBB89_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[8:9] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -4369,7 +5077,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s8 ; GFX9-NEXT: v_mov_b32_e32 v1, s9 -; GFX9-NEXT: .LBB73_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB89_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v8, v1 ; GFX9-NEXT: v_mov_b32_e32 v7, v0 @@ -4382,7 +5090,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] -; GFX9-NEXT: s_cbranch_execnz .LBB73_1 +; GFX9-NEXT: s_cbranch_execnz .LBB89_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] ; GFX9-NEXT: v_mov_b32_e32 v2, 0 @@ -4414,7 +5122,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr addrspace(1) %out, i64 %in, ; SI-NEXT: v_mov_b32_e32 v2, s8 ; SI-NEXT: v_mov_b32_e32 v3, s9 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB74_1: ; %atomicrmw.start +; SI-NEXT: .LBB90_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -4432,7 +5140,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr addrspace(1) %out, i64 %in, ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB74_1 +; SI-NEXT: s_cbranch_execnz .LBB90_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -4453,7 +5161,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr addrspace(1) %out, i64 %in, ; VI-NEXT: v_mov_b32_e32 v2, s6 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v5, s5 -; VI-NEXT: .LBB74_1: ; %atomicrmw.start +; VI-NEXT: .LBB90_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_cmp_lt_i64_e32 vcc, s[2:3], v[2:3] ; VI-NEXT: v_cndmask_b32_e32 v1, v6, v3, vcc @@ -4466,7 +5174,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr addrspace(1) %out, i64 %in, ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB74_1 +; VI-NEXT: s_cbranch_execnz .LBB90_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -4486,7 +5194,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr addrspace(1) %out, i64 %in, ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v2, s4 ; GFX9-NEXT: v_mov_b32_e32 v3, s5 -; GFX9-NEXT: .LBB74_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB90_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[6:7], v[2:3] ; GFX9-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -4499,7 +5207,7 @@ define amdgpu_kernel void @atomic_max_i64_addr64(ptr addrspace(1) %out, i64 %in, ; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX9-NEXT: s_cbranch_execnz .LBB74_1 +; GFX9-NEXT: s_cbranch_execnz .LBB90_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -4525,7 +5233,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: v_mov_b32_e32 v2, s6 ; SI-NEXT: v_mov_b32_e32 v3, s7 ; SI-NEXT: s_mov_b32 s10, -1 -; SI-NEXT: .LBB75_1: ; %atomicrmw.start +; SI-NEXT: .LBB91_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v8, v3, vcc @@ -4543,7 +5251,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB75_1 +; SI-NEXT: s_cbranch_execnz .LBB91_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -4569,7 +5277,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v2, s8 ; VI-NEXT: v_mov_b32_e32 v3, s9 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB75_1: ; %atomicrmw.start +; VI-NEXT: .LBB91_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v9, v3 ; VI-NEXT: v_mov_b32_e32 v8, v2 @@ -4582,7 +5290,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB75_1 +; VI-NEXT: s_cbranch_execnz .LBB91_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -4605,7 +5313,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s8 ; GFX9-NEXT: v_mov_b32_e32 v1, s9 -; GFX9-NEXT: .LBB75_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB91_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v8, v1 ; GFX9-NEXT: v_mov_b32_e32 v7, v0 @@ -4618,7 +5326,7 @@ define amdgpu_kernel void @atomic_max_i64_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] -; GFX9-NEXT: s_cbranch_execnz .LBB75_1 +; GFX9-NEXT: s_cbranch_execnz .LBB91_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] ; GFX9-NEXT: v_mov_b32_e32 v2, 0 @@ -4631,24 +5339,20 @@ entry: ret void } -; --------------------------------------------------------------------- -; atomicrmw umax -; --------------------------------------------------------------------- - -define void @global_atomic_umax_i64_noret(ptr addrspace(1) %ptr, i64 %in) { -; SI-LABEL: global_atomic_umax_i64_noret: +define void @global_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB76_1: ; %atomicrmw.start +; SI-NEXT: .LBB92_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc ; SI-NEXT: s_waitcnt expcnt(0) @@ -4656,7 +5360,7 @@ define void @global_atomic_umax_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v10, v6 ; SI-NEXT: v_mov_b32_e32 v9, v5 ; SI-NEXT: v_mov_b32_e32 v8, v4 -; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 offset:32 glc ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] @@ -4664,21 +5368,23 @@ define void @global_atomic_umax_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB76_1 +; SI-NEXT: s_cbranch_execnz .LBB92_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) ; SI-NEXT: s_setpc_b64 s[30:31] ; -; VI-LABEL: global_atomic_umax_i64_noret: +; VI-LABEL: global_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB76_1: ; %atomicrmw.start +; VI-NEXT: .LBB92_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; VI-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] ; VI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; VI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc ; VI-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc @@ -4689,23 +5395,23 @@ define void @global_atomic_umax_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB76_1 +; VI-NEXT: s_cbranch_execnz .LBB92_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] ; -; GFX9-LABEL: global_atomic_umax_i64_noret: +; GFX9-LABEL: global_atomic_max_i64_noret_offset__amdgpu_no_remote_memory_access: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB76_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB92_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) -; GFX9-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] ; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc -; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off glc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: buffer_wbinvl1_vol ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] @@ -4713,32 +5419,218 @@ define void @global_atomic_umax_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB76_1 +; GFX9-NEXT: s_cbranch_execnz .LBB92_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] - %tmp0 = atomicrmw umax ptr addrspace(1) %ptr, i64 %in seq_cst + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw max ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 ret void } -define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) { -; SI-LABEL: global_atomic_umax_i64_noret_offset: +define i64 @global_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: v_mov_b32_e32 v4, v2 +; SI-NEXT: v_mov_b32_e32 v7, v1 +; SI-NEXT: v_mov_b32_e32 v6, v0 ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB77_1: ; %atomicrmw.start +; SI-NEXT: .LBB93_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] -; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc -; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; SI-NEXT: v_mov_b32_e32 v11, v1 +; SI-NEXT: v_mov_b32_e32 v10, v0 +; SI-NEXT: v_cmp_gt_i64_e32 vcc, v[10:11], v[4:5] +; SI-NEXT: v_cndmask_b32_e32 v9, v5, v11, vcc +; SI-NEXT: v_cndmask_b32_e32 v8, v4, v10, vcc ; SI-NEXT: s_waitcnt expcnt(0) -; SI-NEXT: v_mov_b32_e32 v11, v7 +; SI-NEXT: v_mov_b32_e32 v0, v8 +; SI-NEXT: v_mov_b32_e32 v1, v9 +; SI-NEXT: v_mov_b32_e32 v2, v10 +; SI-NEXT: v_mov_b32_e32 v3, v11 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[0:3], v[6:7], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB93_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB93_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v9, v1 +; VI-NEXT: v_mov_b32_e32 v8, v0 +; VI-NEXT: v_cmp_gt_i64_e32 vcc, v[8:9], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; VI-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB93_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_max_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB93_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB93_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v4 +; GFX9-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw max ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw umax +; --------------------------------------------------------------------- + +define void @global_atomic_umax_i64_noret(ptr addrspace(1) %ptr, i64 %in) { +; SI-LABEL: global_atomic_umax_i64_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB94_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v7 +; SI-NEXT: v_mov_b32_e32 v10, v6 +; SI-NEXT: v_mov_b32_e32 v9, v5 +; SI-NEXT: v_mov_b32_e32 v8, v4 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v6, v8 +; SI-NEXT: v_mov_b32_e32 v7, v9 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB94_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i64_noret: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB94_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; VI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; VI-NEXT: v_mov_b32_e32 v7, v5 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v6, v4 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB94_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umax_i64_noret: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB94_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB94_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %tmp0 = atomicrmw umax ptr addrspace(1) %ptr, i64 %in seq_cst + ret void +} + +define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_umax_i64_noret_offset: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB95_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v7 ; SI-NEXT: v_mov_b32_e32 v10, v6 ; SI-NEXT: v_mov_b32_e32 v9, v5 ; SI-NEXT: v_mov_b32_e32 v8, v4 @@ -4750,7 +5642,7 @@ define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB77_1 +; SI-NEXT: s_cbranch_execnz .LBB95_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -4763,7 +5655,7 @@ define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB77_1: ; %atomicrmw.start +; VI-NEXT: .LBB95_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] @@ -4777,7 +5669,7 @@ define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB77_1 +; VI-NEXT: s_cbranch_execnz .LBB95_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4787,7 +5679,7 @@ define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB77_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB95_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] @@ -4801,7 +5693,7 @@ define void @global_atomic_umax_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB77_1 +; GFX9-NEXT: s_cbranch_execnz .LBB95_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4824,7 +5716,7 @@ define i64 @global_atomic_umax_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB78_1: ; %atomicrmw.start +; SI-NEXT: .LBB96_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -4843,7 +5735,7 @@ define i64 @global_atomic_umax_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB78_1 +; SI-NEXT: s_cbranch_execnz .LBB96_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -4854,7 +5746,7 @@ define i64 @global_atomic_umax_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB78_1: ; %atomicrmw.start +; VI-NEXT: .LBB96_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v5 @@ -4868,7 +5760,7 @@ define i64 @global_atomic_umax_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB78_1 +; VI-NEXT: s_cbranch_execnz .LBB96_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v4 @@ -4880,7 +5772,7 @@ define i64 @global_atomic_umax_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB78_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB96_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -4894,7 +5786,7 @@ define i64 @global_atomic_umax_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB78_1 +; GFX9-NEXT: s_cbranch_execnz .LBB96_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -4918,7 +5810,7 @@ define i64 @global_atomic_umax_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB79_1: ; %atomicrmw.start +; SI-NEXT: .LBB97_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -4937,7 +5829,7 @@ define i64 @global_atomic_umax_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB79_1 +; SI-NEXT: s_cbranch_execnz .LBB97_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -4950,7 +5842,7 @@ define i64 @global_atomic_umax_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB79_1: ; %atomicrmw.start +; VI-NEXT: .LBB97_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -4964,7 +5856,7 @@ define i64 @global_atomic_umax_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB79_1 +; VI-NEXT: s_cbranch_execnz .LBB97_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -4974,7 +5866,7 @@ define i64 @global_atomic_umax_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB79_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB97_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -4988,7 +5880,7 @@ define i64 @global_atomic_umax_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB79_1 +; GFX9-NEXT: s_cbranch_execnz .LBB97_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -5017,7 +5909,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB80_1: ; %atomicrmw.start +; SI-NEXT: .LBB98_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_lt_u64_e32 vcc, s[34:35], v[2:3] @@ -5036,7 +5928,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB80_1 +; SI-NEXT: s_cbranch_execnz .LBB98_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -5058,7 +5950,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 ; VI-NEXT: v_mov_b32_e32 v5, s5 -; VI-NEXT: .LBB80_1: ; %atomicrmw.start +; VI-NEXT: .LBB98_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -5072,7 +5964,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB80_1 +; VI-NEXT: s_cbranch_execnz .LBB98_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5085,7 +5977,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB80_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB98_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -5099,7 +5991,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB80_1 +; GFX9-NEXT: s_cbranch_execnz .LBB98_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5125,7 +6017,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB81_1: ; %atomicrmw.start +; SI-NEXT: .LBB99_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_lt_u64_e32 vcc, s[34:35], v[2:3] @@ -5144,7 +6036,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_offset_scalar(ptr addrspace ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB81_1 +; SI-NEXT: s_cbranch_execnz .LBB99_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -5166,7 +6058,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 -; VI-NEXT: .LBB81_1: ; %atomicrmw.start +; VI-NEXT: .LBB99_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -5180,7 +6072,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB81_1 +; VI-NEXT: s_cbranch_execnz .LBB99_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5193,7 +6085,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB81_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB99_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] @@ -5207,7 +6099,7 @@ define amdgpu_gfx void @global_atomic_umax_i64_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB81_1 +; GFX9-NEXT: s_cbranch_execnz .LBB99_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5234,7 +6126,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB82_1: ; %atomicrmw.start +; SI-NEXT: .LBB100_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -5253,7 +6145,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB82_1 +; SI-NEXT: s_cbranch_execnz .LBB100_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -5275,7 +6167,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 ; VI-NEXT: v_mov_b32_e32 v3, s5 -; VI-NEXT: .LBB82_1: ; %atomicrmw.start +; VI-NEXT: .LBB100_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -5289,7 +6181,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB82_1 +; VI-NEXT: s_cbranch_execnz .LBB100_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5302,7 +6194,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB82_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB100_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -5316,7 +6208,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB82_1 +; GFX9-NEXT: s_cbranch_execnz .LBB100_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5342,7 +6234,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB83_1: ; %atomicrmw.start +; SI-NEXT: .LBB101_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -5361,7 +6253,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB83_1 +; SI-NEXT: s_cbranch_execnz .LBB101_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -5383,7 +6275,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 -; VI-NEXT: .LBB83_1: ; %atomicrmw.start +; VI-NEXT: .LBB101_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -5397,7 +6289,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB83_1 +; VI-NEXT: s_cbranch_execnz .LBB101_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5410,7 +6302,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB83_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB101_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -5424,7 +6316,7 @@ define amdgpu_gfx i64 @global_atomic_umax_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB83_1 +; GFX9-NEXT: s_cbranch_execnz .LBB101_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5451,7 +6343,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr addrspace(1) %out, ; SI-NEXT: v_mov_b32_e32 v2, s8 ; SI-NEXT: v_mov_b32_e32 v3, s9 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB84_1: ; %atomicrmw.start +; SI-NEXT: .LBB102_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_u64_e32 vcc, s[2:3], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -5469,7 +6361,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr addrspace(1) %out, ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB84_1 +; SI-NEXT: s_cbranch_execnz .LBB102_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -5492,7 +6384,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr addrspace(1) %out, ; VI-NEXT: v_mov_b32_e32 v7, s2 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v4, s0 -; VI-NEXT: .LBB84_1: ; %atomicrmw.start +; VI-NEXT: .LBB102_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_cmp_lt_u64_e32 vcc, s[2:3], v[2:3] ; VI-NEXT: v_cndmask_b32_e32 v1, v6, v3, vcc @@ -5505,7 +6397,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr addrspace(1) %out, ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB84_1 +; VI-NEXT: s_cbranch_execnz .LBB102_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -5525,7 +6417,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr addrspace(1) %out, ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v2, s4 ; GFX9-NEXT: v_mov_b32_e32 v3, s5 -; GFX9-NEXT: .LBB84_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB102_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[2:3] ; GFX9-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -5538,7 +6430,7 @@ define amdgpu_kernel void @atomic_umax_i64_addr64_offset(ptr addrspace(1) %out, ; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX9-NEXT: s_cbranch_execnz .LBB84_1 +; GFX9-NEXT: s_cbranch_execnz .LBB102_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -5565,7 +6457,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr addrspace(1) %o ; SI-NEXT: v_mov_b32_e32 v2, s6 ; SI-NEXT: v_mov_b32_e32 v3, s7 ; SI-NEXT: s_mov_b32 s10, -1 -; SI-NEXT: .LBB85_1: ; %atomicrmw.start +; SI-NEXT: .LBB103_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_u64_e32 vcc, s[4:5], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v8, v3, vcc @@ -5583,7 +6475,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr addrspace(1) %o ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB85_1 +; SI-NEXT: s_cbranch_execnz .LBB103_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -5611,7 +6503,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr addrspace(1) %o ; VI-NEXT: v_mov_b32_e32 v5, s4 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v1, s1 -; VI-NEXT: .LBB85_1: ; %atomicrmw.start +; VI-NEXT: .LBB103_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v9, v3 ; VI-NEXT: v_mov_b32_e32 v8, v2 @@ -5624,7 +6516,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr addrspace(1) %o ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; VI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; VI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; VI-NEXT: s_cbranch_execnz .LBB85_1 +; VI-NEXT: s_cbranch_execnz .LBB103_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[8:9] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -5647,7 +6539,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr addrspace(1) %o ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s8 ; GFX9-NEXT: v_mov_b32_e32 v1, s9 -; GFX9-NEXT: .LBB85_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB103_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v8, v1 ; GFX9-NEXT: v_mov_b32_e32 v7, v0 @@ -5660,7 +6552,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64_offset(ptr addrspace(1) %o ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] -; GFX9-NEXT: s_cbranch_execnz .LBB85_1 +; GFX9-NEXT: s_cbranch_execnz .LBB103_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] ; GFX9-NEXT: v_mov_b32_e32 v2, 0 @@ -5691,7 +6583,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: v_mov_b32_e32 v2, s6 ; SI-NEXT: v_mov_b32_e32 v3, s7 ; SI-NEXT: s_mov_b32 s10, -1 -; SI-NEXT: .LBB86_1: ; %atomicrmw.start +; SI-NEXT: .LBB104_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_lt_u64_e32 vcc, s[4:5], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v8, v3, vcc @@ -5709,7 +6601,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB86_1 +; SI-NEXT: s_cbranch_execnz .LBB104_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -5735,7 +6627,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v2, s8 ; VI-NEXT: v_mov_b32_e32 v3, s9 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB86_1: ; %atomicrmw.start +; VI-NEXT: .LBB104_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v9, v3 ; VI-NEXT: v_mov_b32_e32 v8, v2 @@ -5748,7 +6640,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB86_1 +; VI-NEXT: s_cbranch_execnz .LBB104_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -5771,7 +6663,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s8 ; GFX9-NEXT: v_mov_b32_e32 v1, s9 -; GFX9-NEXT: .LBB86_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB104_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v8, v1 ; GFX9-NEXT: v_mov_b32_e32 v7, v0 @@ -5784,7 +6676,7 @@ define amdgpu_kernel void @atomic_umax_i64_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] -; GFX9-NEXT: s_cbranch_execnz .LBB86_1 +; GFX9-NEXT: s_cbranch_execnz .LBB104_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] ; GFX9-NEXT: v_mov_b32_e32 v2, 0 @@ -5797,6 +6689,190 @@ entry: ret void } +define void @global_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB105_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v7 +; SI-NEXT: v_mov_b32_e32 v10, v6 +; SI-NEXT: v_mov_b32_e32 v9, v5 +; SI-NEXT: v_mov_b32_e32 v8, v4 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v6, v8 +; SI-NEXT: v_mov_b32_e32 v7, v9 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB105_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB105_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; VI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; VI-NEXT: v_mov_b32_e32 v7, v5 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v6, v4 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB105_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umax_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB105_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB105_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw umax ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: v_mov_b32_e32 v4, v2 +; SI-NEXT: v_mov_b32_e32 v7, v1 +; SI-NEXT: v_mov_b32_e32 v6, v0 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB106_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v1 +; SI-NEXT: v_mov_b32_e32 v10, v0 +; SI-NEXT: v_cmp_gt_u64_e32 vcc, v[10:11], v[4:5] +; SI-NEXT: v_cndmask_b32_e32 v9, v5, v11, vcc +; SI-NEXT: v_cndmask_b32_e32 v8, v4, v10, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v0, v8 +; SI-NEXT: v_mov_b32_e32 v1, v9 +; SI-NEXT: v_mov_b32_e32 v2, v10 +; SI-NEXT: v_mov_b32_e32 v3, v11 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[0:3], v[6:7], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB106_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB106_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v9, v1 +; VI-NEXT: v_mov_b32_e32 v8, v0 +; VI-NEXT: v_cmp_gt_u64_e32 vcc, v[8:9], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; VI-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB106_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umax_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB106_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB106_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v4 +; GFX9-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw umax ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw umin ; --------------------------------------------------------------------- @@ -5811,7 +6887,7 @@ define void @global_atomic_umin_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB87_1: ; %atomicrmw.start +; SI-NEXT: .LBB107_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5830,7 +6906,7 @@ define void @global_atomic_umin_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB87_1 +; SI-NEXT: s_cbranch_execnz .LBB107_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5841,7 +6917,7 @@ define void @global_atomic_umin_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB87_1: ; %atomicrmw.start +; VI-NEXT: .LBB107_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5855,7 +6931,7 @@ define void @global_atomic_umin_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB87_1 +; VI-NEXT: s_cbranch_execnz .LBB107_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5865,7 +6941,7 @@ define void @global_atomic_umin_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB87_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB107_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5879,7 +6955,7 @@ define void @global_atomic_umin_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB87_1 +; GFX9-NEXT: s_cbranch_execnz .LBB107_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5897,7 +6973,7 @@ define void @global_atomic_umin_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB88_1: ; %atomicrmw.start +; SI-NEXT: .LBB108_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5916,7 +6992,7 @@ define void @global_atomic_umin_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB88_1 +; SI-NEXT: s_cbranch_execnz .LBB108_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -5929,7 +7005,7 @@ define void @global_atomic_umin_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB88_1: ; %atomicrmw.start +; VI-NEXT: .LBB108_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5943,7 +7019,7 @@ define void @global_atomic_umin_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB88_1 +; VI-NEXT: s_cbranch_execnz .LBB108_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -5953,7 +7029,7 @@ define void @global_atomic_umin_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB88_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB108_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] @@ -5967,7 +7043,7 @@ define void @global_atomic_umin_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB88_1 +; GFX9-NEXT: s_cbranch_execnz .LBB108_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -5990,7 +7066,7 @@ define i64 @global_atomic_umin_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB89_1: ; %atomicrmw.start +; SI-NEXT: .LBB109_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -6009,7 +7085,7 @@ define i64 @global_atomic_umin_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB89_1 +; SI-NEXT: s_cbranch_execnz .LBB109_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6020,7 +7096,7 @@ define i64 @global_atomic_umin_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB89_1: ; %atomicrmw.start +; VI-NEXT: .LBB109_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v5 @@ -6034,7 +7110,7 @@ define i64 @global_atomic_umin_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB89_1 +; VI-NEXT: s_cbranch_execnz .LBB109_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v4 @@ -6046,7 +7122,7 @@ define i64 @global_atomic_umin_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB89_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB109_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -6060,7 +7136,7 @@ define i64 @global_atomic_umin_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB89_1 +; GFX9-NEXT: s_cbranch_execnz .LBB109_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -6084,7 +7160,7 @@ define i64 @global_atomic_umin_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB90_1: ; %atomicrmw.start +; SI-NEXT: .LBB110_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -6103,7 +7179,7 @@ define i64 @global_atomic_umin_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB90_1 +; SI-NEXT: s_cbranch_execnz .LBB110_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6116,7 +7192,7 @@ define i64 @global_atomic_umin_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB90_1: ; %atomicrmw.start +; VI-NEXT: .LBB110_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -6130,7 +7206,7 @@ define i64 @global_atomic_umin_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB90_1 +; VI-NEXT: s_cbranch_execnz .LBB110_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6140,7 +7216,7 @@ define i64 @global_atomic_umin_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB90_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB110_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -6154,7 +7230,7 @@ define i64 @global_atomic_umin_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB90_1 +; GFX9-NEXT: s_cbranch_execnz .LBB110_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -6183,7 +7259,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB91_1: ; %atomicrmw.start +; SI-NEXT: .LBB111_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_ge_u64_e32 vcc, s[34:35], v[2:3] @@ -6202,7 +7278,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_scalar(ptr addrspace(1) inr ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB91_1 +; SI-NEXT: s_cbranch_execnz .LBB111_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -6224,7 +7300,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 ; VI-NEXT: v_mov_b32_e32 v5, s5 -; VI-NEXT: .LBB91_1: ; %atomicrmw.start +; VI-NEXT: .LBB111_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -6238,7 +7314,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_scalar(ptr addrspace(1) inr ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB91_1 +; VI-NEXT: s_cbranch_execnz .LBB111_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6251,7 +7327,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB91_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB111_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -6265,7 +7341,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_scalar(ptr addrspace(1) inr ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB91_1 +; GFX9-NEXT: s_cbranch_execnz .LBB111_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6291,7 +7367,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_offset_scalar(ptr addrspace ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB92_1: ; %atomicrmw.start +; SI-NEXT: .LBB112_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_ge_u64_e32 vcc, s[34:35], v[2:3] @@ -6310,7 +7386,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_offset_scalar(ptr addrspace ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB92_1 +; SI-NEXT: s_cbranch_execnz .LBB112_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -6332,7 +7408,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 -; VI-NEXT: .LBB92_1: ; %atomicrmw.start +; VI-NEXT: .LBB112_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -6346,7 +7422,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_offset_scalar(ptr addrspace ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB92_1 +; VI-NEXT: s_cbranch_execnz .LBB112_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6359,7 +7435,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB92_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB112_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_ge_u64_e32 vcc, s[6:7], v[2:3] @@ -6373,7 +7449,7 @@ define amdgpu_gfx void @global_atomic_umin_i64_noret_offset_scalar(ptr addrspace ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB92_1 +; GFX9-NEXT: s_cbranch_execnz .LBB112_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6400,7 +7476,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB93_1: ; %atomicrmw.start +; SI-NEXT: .LBB113_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -6419,7 +7495,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_scalar(ptr addrspace(1) inreg ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB93_1 +; SI-NEXT: s_cbranch_execnz .LBB113_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -6441,7 +7517,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 ; VI-NEXT: v_mov_b32_e32 v3, s5 -; VI-NEXT: .LBB93_1: ; %atomicrmw.start +; VI-NEXT: .LBB113_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -6455,7 +7531,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_scalar(ptr addrspace(1) inreg ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB93_1 +; VI-NEXT: s_cbranch_execnz .LBB113_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6468,7 +7544,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB93_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB113_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -6482,7 +7558,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_scalar(ptr addrspace(1) inreg ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB93_1 +; GFX9-NEXT: s_cbranch_execnz .LBB113_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6508,7 +7584,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB94_1: ; %atomicrmw.start +; SI-NEXT: .LBB114_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -6527,7 +7603,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB94_1 +; SI-NEXT: s_cbranch_execnz .LBB114_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -6549,7 +7625,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 -; VI-NEXT: .LBB94_1: ; %atomicrmw.start +; VI-NEXT: .LBB114_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -6563,7 +7639,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB94_1 +; VI-NEXT: s_cbranch_execnz .LBB114_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6576,7 +7652,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB94_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB114_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -6590,7 +7666,7 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB94_1 +; GFX9-NEXT: s_cbranch_execnz .LBB114_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6599,24 +7675,20 @@ define amdgpu_gfx i64 @global_atomic_umin_i64_ret_offset_scalar(ptr addrspace(1) ret i64 %result } -; --------------------------------------------------------------------- -; atomicrmw min -; --------------------------------------------------------------------- - -define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { -; SI-LABEL: global_atomic_min_i64_noret: +define void @global_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB95_1: ; %atomicrmw.start +; SI-NEXT: .LBB115_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc ; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc ; SI-NEXT: s_waitcnt expcnt(0) @@ -6624,7 +7696,7 @@ define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v10, v6 ; SI-NEXT: v_mov_b32_e32 v9, v5 ; SI-NEXT: v_mov_b32_e32 v8, v4 -; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 offset:32 glc ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: buffer_wbinvl1 ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] @@ -6632,7 +7704,195 @@ define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB95_1 +; SI-NEXT: s_cbranch_execnz .LBB115_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB115_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; VI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; VI-NEXT: v_mov_b32_e32 v7, v5 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v6, v4 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB115_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umin_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB115_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB115_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw umin ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: v_mov_b32_e32 v4, v2 +; SI-NEXT: v_mov_b32_e32 v7, v1 +; SI-NEXT: v_mov_b32_e32 v6, v0 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB116_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v1 +; SI-NEXT: v_mov_b32_e32 v10, v0 +; SI-NEXT: v_cmp_le_u64_e32 vcc, v[10:11], v[4:5] +; SI-NEXT: v_cndmask_b32_e32 v9, v5, v11, vcc +; SI-NEXT: v_cndmask_b32_e32 v8, v4, v10, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v0, v8 +; SI-NEXT: v_mov_b32_e32 v1, v9 +; SI-NEXT: v_mov_b32_e32 v2, v10 +; SI-NEXT: v_mov_b32_e32 v3, v11 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[0:3], v[6:7], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB116_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB116_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v9, v1 +; VI-NEXT: v_mov_b32_e32 v8, v0 +; VI-NEXT: v_cmp_le_u64_e32 vcc, v[8:9], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; VI-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB116_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_umin_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB116_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: v_cmp_le_u64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB116_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v4 +; GFX9-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw umin ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw min +; --------------------------------------------------------------------- + +define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { +; SI-LABEL: global_atomic_min_i64_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB117_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v7 +; SI-NEXT: v_mov_b32_e32 v10, v6 +; SI-NEXT: v_mov_b32_e32 v9, v5 +; SI-NEXT: v_mov_b32_e32 v8, v4 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v6, v8 +; SI-NEXT: v_mov_b32_e32 v7, v9 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB117_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6643,7 +7903,7 @@ define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB95_1: ; %atomicrmw.start +; VI-NEXT: .LBB117_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6657,7 +7917,7 @@ define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB95_1 +; VI-NEXT: s_cbranch_execnz .LBB117_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6667,7 +7927,7 @@ define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB95_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB117_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6681,7 +7941,7 @@ define void @global_atomic_min_i64_noret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB95_1 +; GFX9-NEXT: s_cbranch_execnz .LBB117_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6699,7 +7959,7 @@ define void @global_atomic_min_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB96_1: ; %atomicrmw.start +; SI-NEXT: .LBB118_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6718,7 +7978,7 @@ define void @global_atomic_min_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; SI-NEXT: v_mov_b32_e32 v6, v8 ; SI-NEXT: v_mov_b32_e32 v7, v9 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB96_1 +; SI-NEXT: s_cbranch_execnz .LBB118_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6731,7 +7991,7 @@ define void @global_atomic_min_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB96_1: ; %atomicrmw.start +; VI-NEXT: .LBB118_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6745,7 +8005,7 @@ define void @global_atomic_min_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v6, v4 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB96_1 +; VI-NEXT: s_cbranch_execnz .LBB118_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6755,7 +8015,7 @@ define void @global_atomic_min_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB96_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB118_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] @@ -6769,7 +8029,7 @@ define void @global_atomic_min_i64_noret_offset(ptr addrspace(1) %out, i64 %in) ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v6, v4 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB96_1 +; GFX9-NEXT: s_cbranch_execnz .LBB118_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -6792,7 +8052,7 @@ define i64 @global_atomic_min_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB97_1: ; %atomicrmw.start +; SI-NEXT: .LBB119_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -6811,7 +8071,7 @@ define i64 @global_atomic_min_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB97_1 +; SI-NEXT: s_cbranch_execnz .LBB119_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6822,7 +8082,7 @@ define i64 @global_atomic_min_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; VI-NEXT: flat_load_dwordx2 v[4:5], v[0:1] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB97_1: ; %atomicrmw.start +; VI-NEXT: .LBB119_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v7, v5 @@ -6836,7 +8096,7 @@ define i64 @global_atomic_min_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB97_1 +; VI-NEXT: s_cbranch_execnz .LBB119_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: v_mov_b32_e32 v0, v4 @@ -6848,7 +8108,7 @@ define i64 @global_atomic_min_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB97_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB119_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -6862,7 +8122,7 @@ define i64 @global_atomic_min_i64_ret(ptr addrspace(1) %ptr, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB97_1 +; GFX9-NEXT: s_cbranch_execnz .LBB119_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -6886,7 +8146,7 @@ define i64 @global_atomic_min_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: s_mov_b32 s5, s6 ; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 ; SI-NEXT: s_mov_b64 s[8:9], 0 -; SI-NEXT: .LBB98_1: ; %atomicrmw.start +; SI-NEXT: .LBB120_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v11, v1 @@ -6905,7 +8165,7 @@ define i64 @global_atomic_min_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] ; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB98_1 +; SI-NEXT: s_cbranch_execnz .LBB120_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[8:9] ; SI-NEXT: s_waitcnt expcnt(0) @@ -6918,7 +8178,7 @@ define i64 @global_atomic_min_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc ; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] ; VI-NEXT: s_mov_b64 s[4:5], 0 -; VI-NEXT: .LBB98_1: ; %atomicrmw.start +; VI-NEXT: .LBB120_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -6932,7 +8192,7 @@ define i64 @global_atomic_min_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB98_1 +; VI-NEXT: s_cbranch_execnz .LBB120_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[4:5] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -6942,7 +8202,7 @@ define i64 @global_atomic_min_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 ; GFX9-NEXT: s_mov_b64 s[4:5], 0 -; GFX9-NEXT: .LBB98_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB120_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v7, v5 @@ -6956,7 +8216,7 @@ define i64 @global_atomic_min_i64_ret_offset(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB98_1 +; GFX9-NEXT: s_cbranch_execnz .LBB120_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v0, v4 @@ -6985,7 +8245,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB99_1: ; %atomicrmw.start +; SI-NEXT: .LBB121_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_ge_i64_e32 vcc, s[34:35], v[2:3] @@ -7004,7 +8264,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_scalar(ptr addrspace(1) inre ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB99_1 +; SI-NEXT: s_cbranch_execnz .LBB121_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -7026,7 +8286,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 ; VI-NEXT: v_mov_b32_e32 v5, s5 -; VI-NEXT: .LBB99_1: ; %atomicrmw.start +; VI-NEXT: .LBB121_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -7040,7 +8300,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_scalar(ptr addrspace(1) inre ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB99_1 +; VI-NEXT: s_cbranch_execnz .LBB121_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -7053,7 +8313,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB99_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB121_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -7067,7 +8327,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_scalar(ptr addrspace(1) inre ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB99_1 +; GFX9-NEXT: s_cbranch_execnz .LBB121_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -7093,7 +8353,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_offset_scalar(ptr addrspace( ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB100_1: ; %atomicrmw.start +; SI-NEXT: .LBB122_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cmp_ge_i64_e32 vcc, s[34:35], v[2:3] @@ -7112,7 +8372,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_offset_scalar(ptr addrspace( ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB100_1 +; SI-NEXT: s_cbranch_execnz .LBB122_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -7134,7 +8394,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v6, s7 ; VI-NEXT: v_mov_b32_e32 v7, s6 -; VI-NEXT: .LBB100_1: ; %atomicrmw.start +; VI-NEXT: .LBB122_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -7148,7 +8408,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_offset_scalar(ptr addrspace( ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB100_1 +; VI-NEXT: s_cbranch_execnz .LBB122_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -7161,7 +8421,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v5, s7 ; GFX9-NEXT: v_mov_b32_e32 v6, s6 -; GFX9-NEXT: .LBB100_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB122_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] @@ -7175,7 +8435,7 @@ define amdgpu_gfx void @global_atomic_min_i64_noret_offset_scalar(ptr addrspace( ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB100_1 +; GFX9-NEXT: s_cbranch_execnz .LBB122_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -7202,7 +8462,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB101_1: ; %atomicrmw.start +; SI-NEXT: .LBB123_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -7221,7 +8481,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_scalar(ptr addrspace(1) inreg % ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB101_1 +; SI-NEXT: s_cbranch_execnz .LBB123_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -7243,7 +8503,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 ; VI-NEXT: v_mov_b32_e32 v3, s5 -; VI-NEXT: .LBB101_1: ; %atomicrmw.start +; VI-NEXT: .LBB123_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -7257,7 +8517,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_scalar(ptr addrspace(1) inreg % ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB101_1 +; VI-NEXT: s_cbranch_execnz .LBB123_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -7270,7 +8530,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB101_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB123_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -7284,7 +8544,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_scalar(ptr addrspace(1) inreg % ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB101_1 +; GFX9-NEXT: s_cbranch_execnz .LBB123_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -7310,7 +8570,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: s_mov_b64 s[36:37], 0 ; SI-NEXT: v_mov_b32_e32 v4, s35 ; SI-NEXT: v_mov_b32_e32 v5, s34 -; SI-NEXT: .LBB102_1: ; %atomicrmw.start +; SI-NEXT: .LBB124_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_mov_b32_e32 v9, v1 @@ -7329,7 +8589,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_offset_scalar(ptr addrspace(1) ; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; SI-NEXT: s_or_b64 s[36:37], vcc, s[36:37] ; SI-NEXT: s_andn2_b64 exec, exec, s[36:37] -; SI-NEXT: s_cbranch_execnz .LBB102_1 +; SI-NEXT: s_cbranch_execnz .LBB124_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[36:37] ; SI-NEXT: v_readlane_b32 s7, v10, 1 @@ -7351,7 +8611,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: s_mov_b64 s[34:35], 0 ; VI-NEXT: v_mov_b32_e32 v4, s7 ; VI-NEXT: v_mov_b32_e32 v5, s6 -; VI-NEXT: .LBB102_1: ; %atomicrmw.start +; VI-NEXT: .LBB124_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_mov_b32_e32 v9, v1 @@ -7365,7 +8625,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_offset_scalar(ptr addrspace(1) ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] ; VI-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; VI-NEXT: s_andn2_b64 exec, exec, s[34:35] -; VI-NEXT: s_cbranch_execnz .LBB102_1 +; VI-NEXT: s_cbranch_execnz .LBB124_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[34:35] ; VI-NEXT: s_setpc_b64 s[30:31] @@ -7378,7 +8638,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: s_mov_b64 s[34:35], 0 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 ; GFX9-NEXT: v_mov_b32_e32 v4, s6 -; GFX9-NEXT: .LBB102_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB124_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v8, v1 @@ -7392,7 +8652,7 @@ define amdgpu_gfx i64 @global_atomic_min_i64_ret_offset_scalar(ptr addrspace(1) ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[34:35], vcc, s[34:35] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GFX9-NEXT: s_cbranch_execnz .LBB102_1 +; GFX9-NEXT: s_cbranch_execnz .LBB124_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[34:35] ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -7419,7 +8679,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: v_mov_b32_e32 v2, s8 ; SI-NEXT: v_mov_b32_e32 v3, s9 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB103_1: ; %atomicrmw.start +; SI-NEXT: .LBB125_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -7437,7 +8697,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr addrspace(1) %out, i ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB103_1 +; SI-NEXT: s_cbranch_execnz .LBB125_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -7460,7 +8720,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: v_mov_b32_e32 v7, s2 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v4, s0 -; VI-NEXT: .LBB103_1: ; %atomicrmw.start +; VI-NEXT: .LBB125_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] ; VI-NEXT: v_cndmask_b32_e32 v1, v6, v3, vcc @@ -7473,7 +8733,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr addrspace(1) %out, i ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB103_1 +; VI-NEXT: s_cbranch_execnz .LBB125_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -7493,7 +8753,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v2, s4 ; GFX9-NEXT: v_mov_b32_e32 v3, s5 -; GFX9-NEXT: .LBB103_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB125_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_cmp_ge_i64_e32 vcc, s[6:7], v[2:3] ; GFX9-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -7506,7 +8766,7 @@ define amdgpu_kernel void @atomic_min_i64_addr64_offset(ptr addrspace(1) %out, i ; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX9-NEXT: s_cbranch_execnz .LBB103_1 +; GFX9-NEXT: s_cbranch_execnz .LBB125_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -7533,7 +8793,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: v_mov_b32_e32 v2, s6 ; SI-NEXT: v_mov_b32_e32 v3, s7 ; SI-NEXT: s_mov_b32 s10, -1 -; SI-NEXT: .LBB104_1: ; %atomicrmw.start +; SI-NEXT: .LBB126_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_ge_i64_e32 vcc, s[4:5], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v8, v3, vcc @@ -7551,7 +8811,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr addrspace(1) %ou ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB104_1 +; SI-NEXT: s_cbranch_execnz .LBB126_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -7579,7 +8839,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_mov_b32_e32 v5, s4 ; VI-NEXT: v_mov_b32_e32 v3, s7 ; VI-NEXT: v_mov_b32_e32 v1, s1 -; VI-NEXT: .LBB104_1: ; %atomicrmw.start +; VI-NEXT: .LBB126_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v9, v3 ; VI-NEXT: v_mov_b32_e32 v8, v2 @@ -7592,7 +8852,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr addrspace(1) %ou ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; VI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] ; VI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; VI-NEXT: s_cbranch_execnz .LBB104_1 +; VI-NEXT: s_cbranch_execnz .LBB126_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[8:9] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -7615,7 +8875,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s8 ; GFX9-NEXT: v_mov_b32_e32 v1, s9 -; GFX9-NEXT: .LBB104_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB126_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v8, v1 ; GFX9-NEXT: v_mov_b32_e32 v7, v0 @@ -7628,7 +8888,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64_offset(ptr addrspace(1) %ou ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] -; GFX9-NEXT: s_cbranch_execnz .LBB104_1 +; GFX9-NEXT: s_cbranch_execnz .LBB126_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] ; GFX9-NEXT: v_mov_b32_e32 v2, 0 @@ -7658,7 +8918,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v2, s10 ; SI-NEXT: v_mov_b32_e32 v3, s11 ; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: .LBB105_1: ; %atomicrmw.start +; SI-NEXT: .LBB127_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -7676,7 +8936,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr addrspace(1) %out, i64 %in) { ; SI-NEXT: v_mov_b32_e32 v2, v6 ; SI-NEXT: v_mov_b32_e32 v3, v7 ; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] -; SI-NEXT: s_cbranch_execnz .LBB105_1 +; SI-NEXT: s_cbranch_execnz .LBB127_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_endpgm ; @@ -7693,7 +8953,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: s_waitcnt lgkmcnt(0) ; VI-NEXT: v_mov_b32_e32 v2, s6 ; VI-NEXT: v_mov_b32_e32 v3, s7 -; VI-NEXT: .LBB105_1: ; %atomicrmw.start +; VI-NEXT: .LBB127_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] ; VI-NEXT: v_cndmask_b32_e32 v1, v6, v3, vcc @@ -7706,7 +8966,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr addrspace(1) %out, i64 %in) { ; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; VI-NEXT: v_mov_b32_e32 v2, v0 ; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] -; VI-NEXT: s_cbranch_execnz .LBB105_1 +; VI-NEXT: s_cbranch_execnz .LBB127_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_endpgm ; @@ -7722,7 +8982,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v2, s6 ; GFX9-NEXT: v_mov_b32_e32 v3, s7 -; GFX9-NEXT: .LBB105_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB127_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_cmp_ge_i64_e32 vcc, s[2:3], v[2:3] ; GFX9-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc @@ -7735,7 +8995,7 @@ define amdgpu_kernel void @atomic_min_i64(ptr addrspace(1) %out, i64 %in) { ; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] ; GFX9-NEXT: v_mov_b32_e32 v2, v0 ; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GFX9-NEXT: s_cbranch_execnz .LBB105_1 +; GFX9-NEXT: s_cbranch_execnz .LBB127_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_endpgm entry: @@ -7760,7 +9020,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: v_mov_b32_e32 v2, s6 ; SI-NEXT: v_mov_b32_e32 v3, s7 ; SI-NEXT: s_mov_b32 s10, -1 -; SI-NEXT: .LBB106_1: ; %atomicrmw.start +; SI-NEXT: .LBB128_1: ; %atomicrmw.start ; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: v_cmp_ge_i64_e32 vcc, s[4:5], v[2:3] ; SI-NEXT: v_cndmask_b32_e32 v1, v8, v3, vcc @@ -7778,7 +9038,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr addrspace(1) %out, ptr ; SI-NEXT: v_mov_b32_e32 v2, v4 ; SI-NEXT: v_mov_b32_e32 v3, v5 ; SI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; SI-NEXT: s_cbranch_execnz .LBB106_1 +; SI-NEXT: s_cbranch_execnz .LBB128_1 ; SI-NEXT: ; %bb.2: ; %atomicrmw.end ; SI-NEXT: s_or_b64 exec, exec, s[0:1] ; SI-NEXT: s_mov_b32 s7, 0xf000 @@ -7804,7 +9064,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_mov_b32_e32 v2, s8 ; VI-NEXT: v_mov_b32_e32 v3, s9 ; VI-NEXT: v_mov_b32_e32 v1, s7 -; VI-NEXT: .LBB106_1: ; %atomicrmw.start +; VI-NEXT: .LBB128_1: ; %atomicrmw.start ; VI-NEXT: ; =>This Inner Loop Header: Depth=1 ; VI-NEXT: v_mov_b32_e32 v9, v3 ; VI-NEXT: v_mov_b32_e32 v8, v2 @@ -7817,7 +9077,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr addrspace(1) %out, ptr ; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[8:9] ; VI-NEXT: s_or_b64 s[0:1], vcc, s[0:1] ; VI-NEXT: s_andn2_b64 exec, exec, s[0:1] -; VI-NEXT: s_cbranch_execnz .LBB106_1 +; VI-NEXT: s_cbranch_execnz .LBB128_1 ; VI-NEXT: ; %bb.2: ; %atomicrmw.end ; VI-NEXT: s_or_b64 exec, exec, s[0:1] ; VI-NEXT: v_mov_b32_e32 v0, s2 @@ -7840,7 +9100,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: v_mov_b32_e32 v0, s8 ; GFX9-NEXT: v_mov_b32_e32 v1, s9 -; GFX9-NEXT: .LBB106_1: ; %atomicrmw.start +; GFX9-NEXT: .LBB128_1: ; %atomicrmw.start ; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX9-NEXT: v_mov_b32_e32 v8, v1 ; GFX9-NEXT: v_mov_b32_e32 v7, v0 @@ -7853,7 +9113,7 @@ define amdgpu_kernel void @atomic_min_i64_ret_addr64(ptr addrspace(1) %out, ptr ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[7:8] ; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] ; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] -; GFX9-NEXT: s_cbranch_execnz .LBB106_1 +; GFX9-NEXT: s_cbranch_execnz .LBB128_1 ; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end ; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] ; GFX9-NEXT: v_mov_b32_e32 v2, 0 @@ -7866,24 +9126,208 @@ entry: ret void } -; --------------------------------------------------------------------- -; atomicrmw uinc_wrap -; --------------------------------------------------------------------- - -define void @global_atomic_uinc_wrap_i64_noret(ptr addrspace(1) %ptr, i64 %in) { -; SI-LABEL: global_atomic_uinc_wrap_i64_noret: +define void @global_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: s_mov_b32 s6, 0 ; SI-NEXT: s_mov_b32 s7, 0xf000 ; SI-NEXT: s_mov_b32 s4, s6 ; SI-NEXT: s_mov_b32 s5, s6 -; SI-NEXT: buffer_atomic_inc_x2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: buffer_load_dwordx2 v[6:7], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB129_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; SI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; SI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc ; SI-NEXT: s_waitcnt expcnt(0) -; SI-NEXT: s_setpc_b64 s[30:31] -; +; SI-NEXT: v_mov_b32_e32 v11, v7 +; SI-NEXT: v_mov_b32_e32 v10, v6 +; SI-NEXT: v_mov_b32_e32 v9, v5 +; SI-NEXT: v_mov_b32_e32 v8, v4 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[8:11], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[8:9], v[6:7] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: v_mov_b32_e32 v6, v8 +; SI-NEXT: v_mov_b32_e32 v7, v9 +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB129_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[6:7], v[0:1] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB129_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; VI-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; VI-NEXT: v_mov_b32_e32 v7, v5 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v6, v4 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB129_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_min_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB129_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB129_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw min ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: v_mov_b32_e32 v5, v3 +; SI-NEXT: v_mov_b32_e32 v4, v2 +; SI-NEXT: v_mov_b32_e32 v7, v1 +; SI-NEXT: v_mov_b32_e32 v6, v0 +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_load_dwordx2 v[0:1], v[6:7], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_mov_b64 s[8:9], 0 +; SI-NEXT: .LBB130_1: ; %atomicrmw.start +; SI-NEXT: ; =>This Inner Loop Header: Depth=1 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_mov_b32_e32 v11, v1 +; SI-NEXT: v_mov_b32_e32 v10, v0 +; SI-NEXT: v_cmp_le_i64_e32 vcc, v[10:11], v[4:5] +; SI-NEXT: v_cndmask_b32_e32 v9, v5, v11, vcc +; SI-NEXT: v_cndmask_b32_e32 v8, v4, v10, vcc +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: v_mov_b32_e32 v0, v8 +; SI-NEXT: v_mov_b32_e32 v1, v9 +; SI-NEXT: v_mov_b32_e32 v2, v10 +; SI-NEXT: v_mov_b32_e32 v3, v11 +; SI-NEXT: buffer_atomic_cmpswap_x2 v[0:3], v[6:7], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[10:11] +; SI-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; SI-NEXT: s_andn2_b64 exec, exec, s[8:9] +; SI-NEXT: s_cbranch_execnz .LBB130_1 +; SI-NEXT: ; %bb.2: ; %atomicrmw.end +; SI-NEXT: s_or_b64 exec, exec, s[8:9] +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v4, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dwordx2 v[0:1], v[4:5] +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB130_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v9, v1 +; VI-NEXT: v_mov_b32_e32 v8, v0 +; VI-NEXT: v_cmp_le_i64_e32 vcc, v[8:9], v[2:3] +; VI-NEXT: v_cndmask_b32_e32 v7, v3, v9, vcc +; VI-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc +; VI-NEXT: flat_atomic_cmpswap_x2 v[0:1], v[4:5], v[6:9] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[8:9] +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB130_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_min_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:32 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB130_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v7, v5 +; GFX9-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-NEXT: v_cmp_le_i64_e32 vcc, v[6:7], v[2:3] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v3, v7, vcc +; GFX9-NEXT: v_cndmask_b32_e32 v4, v2, v6, vcc +; GFX9-NEXT: global_atomic_cmpswap_x2 v[4:5], v[0:1], v[4:7], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[6:7] +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB130_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v4 +; GFX9-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw min ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +; --------------------------------------------------------------------- +; atomicrmw uinc_wrap +; --------------------------------------------------------------------- + +define void @global_atomic_uinc_wrap_i64_noret(ptr addrspace(1) %ptr, i64 %in) { +; SI-LABEL: global_atomic_uinc_wrap_i64_noret: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_inc_x2 v[2:3], v[0:1], s[4:7], 0 addr64 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; ; VI-LABEL: global_atomic_uinc_wrap_i64_noret: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -8230,6 +9674,80 @@ define amdgpu_gfx i64 @global_atomic_uinc_wrap_i64_ret_offset_scalar(ptr addrspa ret i64 %result } +define void @global_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_inc_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_inc_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_uinc_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_inc_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw uinc_wrap ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_inc_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_inc_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_uinc_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_inc_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw uinc_wrap ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + ; --------------------------------------------------------------------- ; atomicrmw udec_wrap ; --------------------------------------------------------------------- @@ -8593,3 +10111,79 @@ define amdgpu_gfx i64 @global_atomic_udec_wrap_i64_ret_offset_scalar(ptr addrspa %result = atomicrmw udec_wrap ptr addrspace(1) %gep, i64 %in seq_cst ret i64 %result } + +define void @global_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_dec_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_dec_x2 v[0:1], v[2:3] +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_udec_wrap_i64_noret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_dec_x2 v[0:1], v[2:3], off offset:32 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %tmp0 = atomicrmw udec_wrap ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define i64 @global_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access(ptr addrspace(1) %out, i64 %in) { +; SI-LABEL: global_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; SI: ; %bb.0: +; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SI-NEXT: s_mov_b32 s6, 0 +; SI-NEXT: s_mov_b32 s7, 0xf000 +; SI-NEXT: s_mov_b32 s4, s6 +; SI-NEXT: s_mov_b32 s5, s6 +; SI-NEXT: buffer_atomic_dec_x2 v[2:3], v[0:1], s[4:7], 0 addr64 offset:32 glc +; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: buffer_wbinvl1 +; SI-NEXT: v_mov_b32_e32 v0, v2 +; SI-NEXT: v_mov_b32_e32 v1, v3 +; SI-NEXT: s_waitcnt expcnt(0) +; SI-NEXT: s_setpc_b64 s[30:31] +; +; VI-LABEL: global_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u32_e32 v0, vcc, 32, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_atomic_dec_x2 v[0:1], v[0:1], v[2:3] glc +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_wbinvl1_vol +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: global_atomic_udec_wrap_i64_ret_offset__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: global_atomic_dec_x2 v[0:1], v[0:1], v[2:3], off offset:32 glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: buffer_wbinvl1_vol +; GFX9-NEXT: s_setpc_b64 s[30:31] + %gep = getelementptr i64, ptr addrspace(1) %out, i64 4 + %result = atomicrmw udec_wrap ptr addrspace(1) %gep, i64 %in seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %result +} + +!0 = !{} diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll index d8e527828af5..794c87b88831 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll @@ -10986,9 +10986,750 @@ define amdgpu_kernel void @global_atomic_fadd_double_uni_address_div_value_defau ret void } +define amdgpu_kernel void @global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr) { +; GFX7LESS-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b64 s[2:3], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s2, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s3, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB18_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dword s6, s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX7LESS-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s6 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap v[3:4], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, v3, v1 +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v1, v3 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB18_2 +; GFX7LESS-NEXT: .LBB18_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b64 s[2:3], exec +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-NEXT: s_cbranch_execz .LBB18_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_bcnt1_i32_b64 s5, s[2:3] +; GFX9-NEXT: v_cvt_f32_ubyte0_e32 v0, s5 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX9-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB18_2 +; GFX9-NEXT: .LBB18_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB18_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, 0 +; GFX1064-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v1, s4 +; GFX1064-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1064-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1064-NEXT: .LBB18_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB18_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1032-NEXT: v_mov_b32_e32 v3, 0 +; GFX1032-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1032-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v1, s4 +; GFX1032-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1032-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1032-NEXT: .LBB18_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_mov_b64 s[4:5], exec +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB18_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, 0 +; GFX1164-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v1, s4 +; GFX1164-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1164-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1164-NEXT: .LBB18_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1132-NEXT: s_mov_b32 s4, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB18_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1132-NEXT: v_mov_b32_e32 v3, 0 +; GFX1132-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_dual_mul_f32 v2, 4.0, v0 :: v_dual_mov_b32 v1, s4 +; GFX1132-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1132-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1132-NEXT: .LBB18_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB18_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s5, s[2:3] +; GFX9-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s5 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-DPP-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX9-DPP-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB18_2 +; GFX9-DPP-NEXT: .LBB18_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB18_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1064-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX1064-DPP-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1064-DPP-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1064-DPP-NEXT: .LBB18_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB18_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1032-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1032-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX1032-DPP-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1032-DPP-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1032-DPP-NEXT: .LBB18_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], exec +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB18_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1164-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX1164-DPP-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1164-DPP-NEXT: .LBB18_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s4, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB18_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1132-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_dual_mul_f32 v2, 4.0, v0 :: v_dual_mov_b32 v1, s4 +; GFX1132-DPP-NEXT: .LBB18_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB18_2 +; GFX1132-DPP-NEXT: .LBB18_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fadd ptr addrspace(1) %ptr, float 4.0 monotonic, align 4, !amdgpu.no.fine.grained.memory !1, !amdgpu.no.remote.memory.access !1, !amdgpu.ignore.denormal.mode !1 + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr) { +; GFX7LESS-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b64 s[2:3], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s2, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s3, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB19_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dword s6, s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX7LESS-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s6 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap v[3:4], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, v3, v1 +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v1, v3 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB19_2 +; GFX7LESS-NEXT: .LBB19_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b64 s[2:3], exec +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-NEXT: s_cbranch_execz .LBB19_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_bcnt1_i32_b64 s5, s[2:3] +; GFX9-NEXT: v_cvt_f32_ubyte0_e32 v0, s5 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX9-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB19_2 +; GFX9-NEXT: .LBB19_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB19_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, 0 +; GFX1064-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v1, s4 +; GFX1064-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1064-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1064-NEXT: .LBB19_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB19_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1032-NEXT: v_mov_b32_e32 v3, 0 +; GFX1032-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1032-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v1, s4 +; GFX1032-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1032-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1032-NEXT: .LBB19_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_mov_b64 s[4:5], exec +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB19_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, 0 +; GFX1164-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v1, s4 +; GFX1164-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1164-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1164-NEXT: .LBB19_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1132-NEXT: s_mov_b32 s4, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB19_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1132-NEXT: v_mov_b32_e32 v3, 0 +; GFX1132-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_dual_mul_f32 v2, 4.0, v0 :: v_dual_mov_b32 v1, s4 +; GFX1132-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1132-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1132-NEXT: .LBB19_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB19_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s5, s[2:3] +; GFX9-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s5 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-DPP-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX9-DPP-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB19_2 +; GFX9-DPP-NEXT: .LBB19_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB19_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1064-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX1064-DPP-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1064-DPP-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1064-DPP-NEXT: .LBB19_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB19_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1032-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1032-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX1032-DPP-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1032-DPP-NEXT: global_atomic_cmpswap v0, v3, v[0:1], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1032-DPP-NEXT: .LBB19_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], exec +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB19_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1164-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mul_f32_e32 v2, 4.0, v0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX1164-DPP-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1164-DPP-NEXT: .LBB19_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s4, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB19_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s3, s3 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v3, 0 +; GFX1132-DPP-NEXT: v_cvt_f32_ubyte0_e32 v0, s3 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b32 s4, s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_dual_mul_f32 v2, 4.0, v0 :: v_dual_mov_b32 v1, s4 +; GFX1132-DPP-NEXT: .LBB19_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f32_e32 v0, v1, v2 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b32 v0, v3, v[0:1], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB19_2 +; GFX1132-DPP-NEXT: .LBB19_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fadd ptr addrspace(1) %ptr, float 4.0 monotonic, align 4, !amdgpu.no.fine.grained.memory !1, !amdgpu.no.remote.memory.access !1 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #1 = { strictfp "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #2 = { strictfp } !llvm.module.flags = !{!0} !0 = !{i32 1, !"amdhsa_code_object_version", i32 500} +!1 = !{} diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll index fde834118432..4c829f302e05 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll @@ -7510,7 +7510,679 @@ define amdgpu_kernel void @global_atomic_fmax_double_uni_address_div_value_defau ret void } +define amdgpu_kernel void @global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr) { +; GFX7LESS-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB12_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s2 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_mul_f32_e32 v0, 1.0, v1 +; GFX7LESS-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap v[2:3], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v1, v2 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB12_2 +; GFX7LESS-NEXT: .LBB12_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB12_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB12_2 +; GFX9-NEXT: .LBB12_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB12_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1064-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1064-NEXT: .LBB12_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB12_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1032-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1032-NEXT: .LBB12_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB12_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1164-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1164-NEXT: .LBB12_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB12_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1132-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1132-NEXT: .LBB12_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX9-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX9-DPP-NEXT: .LBB12_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1064-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1064-DPP-NEXT: .LBB12_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1032-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1032-DPP-NEXT: .LBB12_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1164-DPP-NEXT: .LBB12_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1132-DPP-NEXT: .LBB12_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmax ptr addrspace(1) %ptr, float 4.0 monotonic, align 4, !amdgpu.no.fine.grained.memory !1, !amdgpu.no.remote.memory.access !1, !amdgpu.ignore.denormal.mode !1 + ret void +} + +define amdgpu_kernel void @global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr) { +; GFX7LESS-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB13_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s2 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_mul_f32_e32 v0, 1.0, v1 +; GFX7LESS-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap v[2:3], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v1, v2 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB13_2 +; GFX7LESS-NEXT: .LBB13_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-NEXT: .LBB13_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1064-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-NEXT: .LBB13_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1032-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-NEXT: .LBB13_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1164-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-NEXT: .LBB13_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1132-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-NEXT: .LBB13_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX9-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-DPP-NEXT: .LBB13_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1064-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-DPP-NEXT: .LBB13_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1032-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-DPP-NEXT: .LBB13_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-DPP-NEXT: .LBB13_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-DPP-NEXT: v_max_f32_e32 v0, 4.0, v0 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-DPP-NEXT: .LBB13_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmax ptr addrspace(1) %ptr, float 4.0 monotonic, align 4, !amdgpu.no.fine.grained.memory !1, !amdgpu.no.remote.memory.access !1 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } !llvm.module.flags = !{!0} !0 = !{i32 1, !"amdhsa_code_object_version", i32 500} +!1 = !{} + diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll index 2cedb3e481ee..0b889d9eb0a5 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll @@ -7510,7 +7510,678 @@ define amdgpu_kernel void @global_atomic_fmin_double_uni_address_div_value_defau ret void } +define amdgpu_kernel void @global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr) { +; GFX7LESS-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB12_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s2 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_mul_f32_e32 v0, 1.0, v1 +; GFX7LESS-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap v[2:3], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v1, v2 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB12_2 +; GFX7LESS-NEXT: .LBB12_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB12_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB12_2 +; GFX9-NEXT: .LBB12_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB12_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1064-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1064-NEXT: .LBB12_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB12_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1032-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1032-NEXT: .LBB12_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB12_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1164-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1164-NEXT: .LBB12_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB12_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1132-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1132-NEXT: .LBB12_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX9-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX9-DPP-NEXT: .LBB12_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1064-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1064-DPP-NEXT: .LBB12_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1032-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1032-DPP-NEXT: .LBB12_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1164-DPP-NEXT: .LBB12_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB12_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-DPP-NEXT: .LBB12_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB12_2 +; GFX1132-DPP-NEXT: .LBB12_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmin ptr addrspace(1) %ptr, float 4.0 monotonic, align 4, !amdgpu.no.fine.grained.memory !1, !amdgpu.no.remote.memory.access !1, !amdgpu.ignore.denormal.mode !1 + ret void +} + +define amdgpu_kernel void @global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr) { +; GFX7LESS-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB13_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s2 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_mul_f32_e32 v0, 1.0, v1 +; GFX7LESS-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap v[2:3], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v1, v2 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB13_2 +; GFX7LESS-NEXT: .LBB13_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX9-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-NEXT: .LBB13_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1064-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-NEXT: .LBB13_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1032-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-NEXT: .LBB13_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1164-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-NEXT: .LBB13_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1132-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-NEXT: .LBB13_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dword s4, s[0:1], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX9-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX9-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-DPP-NEXT: .LBB13_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dword s2, s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1064-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1064-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-DPP-NEXT: .LBB13_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dword s3, s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1032-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1032-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1032-DPP-NEXT: global_atomic_cmpswap v0, v2, v[0:1], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-DPP-NEXT: .LBB13_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b32 s2, s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1164-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-DPP-NEXT: .LBB13_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_uni_address_uni_value_system_scope__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v2, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b32 s3, s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, s3 +; GFX1132-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f32_e32 v0, v1, v1 +; GFX1132-DPP-NEXT: v_min_f32_e32 v0, 4.0, v0 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b32 v0, v2, v[0:1], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, v0, v1 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-DPP-NEXT: .LBB13_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmin ptr addrspace(1) %ptr, float 4.0 monotonic, align 4, !amdgpu.no.fine.grained.memory !1, !amdgpu.no.remote.memory.access !1 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } !llvm.module.flags = !{!0} !0 = !{i32 1, !"amdhsa_code_object_version", i32 500} +!1 = !{} diff --git a/llvm/test/CodeGen/AMDGPU/local-atomics-fp.ll b/llvm/test/CodeGen/AMDGPU/local-atomics-fp.ll index 4477f028c6d2..89abdb2b754a 100644 --- a/llvm/test/CodeGen/AMDGPU/local-atomics-fp.ll +++ b/llvm/test/CodeGen/AMDGPU/local-atomics-fp.ll @@ -1673,3 +1673,713 @@ define void @lds_atomic_fadd_noret_bf16(ptr addrspace(3) %ptr) nounwind { %result = atomicrmw fadd ptr addrspace(3) %ptr, bfloat 4.0 seq_cst ret void } + +define float @lds_atomic_fadd_ret_f32__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr) { +; VI-LABEL: lds_atomic_fadd_ret_f32__amdgpu_ignore_denormal_mode: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, 4.0 +; VI-NEXT: s_mov_b32 m0, -1 +; VI-NEXT: ds_add_rtn_f32 v0, v0, v1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: lds_atomic_fadd_ret_f32__amdgpu_ignore_denormal_mode: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, 4.0 +; GFX9-NEXT: ds_add_rtn_f32 v0, v0, v1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX7-LABEL: lds_atomic_fadd_ret_f32__amdgpu_ignore_denormal_mode: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: s_mov_b32 m0, -1 +; GFX7-NEXT: ds_read_b32 v1, v0 +; GFX7-NEXT: s_mov_b64 s[4:5], 0 +; GFX7-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX7-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_mov_b32_e32 v2, v1 +; GFX7-NEXT: v_add_f32_e32 v1, 4.0, v2 +; GFX7-NEXT: ds_cmpst_rtn_b32 v1, v0, v2, v1 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_cmp_eq_u32_e32 vcc, v1, v2 +; GFX7-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_cbranch_execnz .LBB12_1 +; GFX7-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX7-NEXT: v_mov_b32_e32 v0, v1 +; GFX7-NEXT: s_setpc_b64 s[30:31] +; +; GFX8-LABEL: lds_atomic_fadd_ret_f32__amdgpu_ignore_denormal_mode: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: ds_read_b32 v1, v0 +; GFX8-NEXT: s_mov_b64 s[4:5], 0 +; GFX8-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX8-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_mov_b32_e32 v2, v1 +; GFX8-NEXT: v_add_f32_e32 v1, 4.0, v2 +; GFX8-NEXT: ds_cmpst_rtn_b32 v1, v0, v2, v1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, v1, v2 +; GFX8-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX8-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_cbranch_execnz .LBB12_1 +; GFX8-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX8-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX8-NEXT: v_mov_b32_e32 v0, v1 +; GFX8-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(3) %ptr, float 4.0 seq_cst, !amdgpu.ignore.denormal.mode !0 + ret float %result +} + +define void @lds_atomic_fadd_noret_f32__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr) { +; VI-LABEL: lds_atomic_fadd_noret_f32__amdgpu_ignore_denormal_mode: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, 4.0 +; VI-NEXT: s_mov_b32 m0, -1 +; VI-NEXT: ds_add_f32 v0, v1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: lds_atomic_fadd_noret_f32__amdgpu_ignore_denormal_mode: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, 4.0 +; GFX9-NEXT: ds_add_f32 v0, v1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX7-LABEL: lds_atomic_fadd_noret_f32__amdgpu_ignore_denormal_mode: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: s_mov_b32 m0, -1 +; GFX7-NEXT: ds_read_b32 v1, v0 +; GFX7-NEXT: s_mov_b64 s[4:5], 0 +; GFX7-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX7-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_add_f32_e32 v2, 4.0, v1 +; GFX7-NEXT: ds_cmpst_rtn_b32 v2, v0, v1, v2 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; GFX7-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7-NEXT: v_mov_b32_e32 v1, v2 +; GFX7-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_cbranch_execnz .LBB13_1 +; GFX7-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_setpc_b64 s[30:31] +; +; GFX8-LABEL: lds_atomic_fadd_noret_f32__amdgpu_ignore_denormal_mode: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: ds_read_b32 v1, v0 +; GFX8-NEXT: s_mov_b64 s[4:5], 0 +; GFX8-NEXT: .LBB13_1: ; %atomicrmw.start +; GFX8-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_add_f32_e32 v2, 4.0, v1 +; GFX8-NEXT: ds_cmpst_rtn_b32 v2, v0, v1, v2 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, v2, v1 +; GFX8-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX8-NEXT: v_mov_b32_e32 v1, v2 +; GFX8-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_cbranch_execnz .LBB13_1 +; GFX8-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX8-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(3) %ptr, float 4.0 seq_cst, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define <2 x half> @lds_atomic_fadd_ret_v2f16(ptr addrspace(3) %ptr, <2 x half> %val) { +; VI-LABEL: lds_atomic_fadd_ret_v2f16: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: s_mov_b32 m0, -1 +; VI-NEXT: ds_read_b32 v2, v0 +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB14_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v3, v2 +; VI-NEXT: v_add_f16_sdwa v2, v3, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: v_add_f16_e32 v4, v3, v1 +; VI-NEXT: v_or_b32_e32 v2, v4, v2 +; VI-NEXT: ds_cmpst_rtn_b32 v2, v0, v3, v2 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB14_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: v_mov_b32_e32 v0, v2 +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: lds_atomic_fadd_ret_v2f16: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: ds_read_b32 v2, v0 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v3, v2 +; GFX9-NEXT: v_pk_add_f16 v2, v3, v1 +; GFX9-NEXT: ds_cmpst_rtn_b32 v2, v0, v3, v2 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v2, v3 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB14_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v0, v2 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX7-LABEL: lds_atomic_fadd_ret_v2f16: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: s_mov_b32 m0, -1 +; GFX7-NEXT: ds_read_b32 v3, v0 +; GFX7-NEXT: v_cvt_f16_f32_e32 v4, v2 +; GFX7-NEXT: v_cvt_f16_f32_e32 v5, v1 +; GFX7-NEXT: s_mov_b64 s[4:5], 0 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_lshrrev_b32_e32 v2, 16, v3 +; GFX7-NEXT: v_cvt_f32_f16_e32 v1, v2 +; GFX7-NEXT: v_cvt_f32_f16_e32 v2, v3 +; GFX7-NEXT: v_cvt_f32_f16_e32 v3, v4 +; GFX7-NEXT: v_cvt_f32_f16_e32 v4, v5 +; GFX7-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX7-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7-NEXT: v_cvt_f16_f32_e32 v1, v1 +; GFX7-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX7-NEXT: v_cvt_f32_f16_e32 v5, v1 +; GFX7-NEXT: v_cvt_f32_f16_e32 v6, v2 +; GFX7-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX7-NEXT: v_or_b32_e32 v7, v2, v1 +; GFX7-NEXT: v_add_f32_e32 v5, v5, v3 +; GFX7-NEXT: v_add_f32_e32 v6, v6, v4 +; GFX7-NEXT: v_cvt_f16_f32_e32 v5, v5 +; GFX7-NEXT: v_cvt_f16_f32_e32 v6, v6 +; GFX7-NEXT: v_lshlrev_b32_e32 v1, 16, v5 +; GFX7-NEXT: v_or_b32_e32 v1, v6, v1 +; GFX7-NEXT: ds_cmpst_rtn_b32 v5, v0, v7, v1 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_lshrrev_b32_e32 v1, 16, v5 +; GFX7-NEXT: v_cvt_f32_f16_e32 v2, v5 +; GFX7-NEXT: v_cvt_f32_f16_e32 v1, v1 +; GFX7-NEXT: v_cmp_eq_u32_e32 vcc, v5, v7 +; GFX7-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_cbranch_execnz .LBB14_1 +; GFX7-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX7-NEXT: v_mov_b32_e32 v0, v2 +; GFX7-NEXT: s_setpc_b64 s[30:31] +; +; GFX8-LABEL: lds_atomic_fadd_ret_v2f16: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: ds_read_b32 v3, v0 +; GFX8-NEXT: v_cvt_f16_f32_e32 v4, v2 +; GFX8-NEXT: v_cvt_f16_f32_e32 v5, v1 +; GFX8-NEXT: s_mov_b64 s[4:5], 0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_lshrrev_b32_e32 v2, 16, v3 +; GFX8-NEXT: v_cvt_f32_f16_e32 v1, v2 +; GFX8-NEXT: v_cvt_f32_f16_e32 v2, v3 +; GFX8-NEXT: v_cvt_f32_f16_e32 v3, v4 +; GFX8-NEXT: v_cvt_f32_f16_e32 v4, v5 +; GFX8-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX8-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX8-NEXT: v_cvt_f16_f32_e32 v1, v1 +; GFX8-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX8-NEXT: v_cvt_f32_f16_e32 v5, v1 +; GFX8-NEXT: v_cvt_f32_f16_e32 v6, v2 +; GFX8-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX8-NEXT: v_or_b32_e32 v7, v2, v1 +; GFX8-NEXT: v_add_f32_e32 v5, v5, v3 +; GFX8-NEXT: v_add_f32_e32 v6, v6, v4 +; GFX8-NEXT: v_cvt_f16_f32_e32 v5, v5 +; GFX8-NEXT: v_cvt_f16_f32_e32 v6, v6 +; GFX8-NEXT: v_lshlrev_b32_e32 v1, 16, v5 +; GFX8-NEXT: v_or_b32_e32 v1, v6, v1 +; GFX8-NEXT: ds_cmpst_rtn_b32 v5, v0, v7, v1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_lshrrev_b32_e32 v1, 16, v5 +; GFX8-NEXT: v_cvt_f32_f16_e32 v2, v5 +; GFX8-NEXT: v_cvt_f32_f16_e32 v1, v1 +; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, v5, v7 +; GFX8-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX8-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_cbranch_execnz .LBB14_1 +; GFX8-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX8-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX8-NEXT: v_mov_b32_e32 v0, v2 +; GFX8-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(3) %ptr, <2 x half> %val seq_cst + ret <2 x half> %result +} + +define void @lds_atomic_fadd_noret_v2f16(ptr addrspace(3) %ptr, <2 x half> %val) { +; VI-LABEL: lds_atomic_fadd_noret_v2f16: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: s_mov_b32 m0, -1 +; VI-NEXT: ds_read_b32 v2, v0 +; VI-NEXT: s_mov_b64 s[4:5], 0 +; VI-NEXT: .LBB15_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_add_f16_sdwa v3, v2, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: v_add_f16_e32 v4, v2, v1 +; VI-NEXT: v_or_b32_e32 v3, v4, v3 +; VI-NEXT: ds_cmpst_rtn_b32 v3, v0, v2, v3 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v3, v2 +; VI-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; VI-NEXT: v_mov_b32_e32 v2, v3 +; VI-NEXT: s_andn2_b64 exec, exec, s[4:5] +; VI-NEXT: s_cbranch_execnz .LBB15_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[4:5] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: lds_atomic_fadd_noret_v2f16: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: ds_read_b32 v2, v0 +; GFX9-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_pk_add_f16 v3, v2, v1 +; GFX9-NEXT: ds_cmpst_rtn_b32 v3, v0, v2, v3 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v3, v2 +; GFX9-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-NEXT: v_mov_b32_e32 v2, v3 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_cbranch_execnz .LBB15_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX7-LABEL: lds_atomic_fadd_noret_v2f16: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: s_mov_b32 m0, -1 +; GFX7-NEXT: ds_read_b32 v3, v0 +; GFX7-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX7-NEXT: v_cvt_f16_f32_e32 v5, v1 +; GFX7-NEXT: s_mov_b64 s[4:5], 0 +; GFX7-NEXT: v_cvt_f32_f16_e32 v1, v2 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_lshrrev_b32_e32 v4, 16, v3 +; GFX7-NEXT: v_cvt_f32_f16_e32 v4, v4 +; GFX7-NEXT: v_cvt_f32_f16_e32 v3, v3 +; GFX7-NEXT: v_cvt_f32_f16_e32 v2, v5 +; GFX7-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX7-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7-NEXT: v_cvt_f16_f32_e32 v4, v4 +; GFX7-NEXT: v_cvt_f16_f32_e32 v3, v3 +; GFX7-NEXT: v_cvt_f32_f16_e32 v5, v4 +; GFX7-NEXT: v_cvt_f32_f16_e32 v6, v3 +; GFX7-NEXT: v_lshlrev_b32_e32 v4, 16, v4 +; GFX7-NEXT: v_or_b32_e32 v7, v3, v4 +; GFX7-NEXT: v_add_f32_e32 v5, v5, v1 +; GFX7-NEXT: v_add_f32_e32 v6, v6, v2 +; GFX7-NEXT: v_cvt_f16_f32_e32 v5, v5 +; GFX7-NEXT: v_cvt_f16_f32_e32 v6, v6 +; GFX7-NEXT: v_lshlrev_b32_e32 v3, 16, v5 +; GFX7-NEXT: v_or_b32_e32 v3, v6, v3 +; GFX7-NEXT: ds_cmpst_rtn_b32 v5, v0, v7, v3 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_lshrrev_b32_e32 v4, 16, v5 +; GFX7-NEXT: v_cvt_f32_f16_e32 v3, v5 +; GFX7-NEXT: v_cvt_f32_f16_e32 v4, v4 +; GFX7-NEXT: v_cmp_eq_u32_e32 vcc, v5, v7 +; GFX7-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_cbranch_execnz .LBB15_1 +; GFX7-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_setpc_b64 s[30:31] +; +; GFX8-LABEL: lds_atomic_fadd_noret_v2f16: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: ds_read_b32 v3, v0 +; GFX8-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX8-NEXT: v_cvt_f16_f32_e32 v5, v1 +; GFX8-NEXT: s_mov_b64 s[4:5], 0 +; GFX8-NEXT: v_cvt_f32_f16_e32 v1, v2 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v3 +; GFX8-NEXT: v_cvt_f32_f16_e32 v4, v4 +; GFX8-NEXT: v_cvt_f32_f16_e32 v3, v3 +; GFX8-NEXT: v_cvt_f32_f16_e32 v2, v5 +; GFX8-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX8-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX8-NEXT: v_cvt_f16_f32_e32 v4, v4 +; GFX8-NEXT: v_cvt_f16_f32_e32 v3, v3 +; GFX8-NEXT: v_cvt_f32_f16_e32 v5, v4 +; GFX8-NEXT: v_cvt_f32_f16_e32 v6, v3 +; GFX8-NEXT: v_lshlrev_b32_e32 v4, 16, v4 +; GFX8-NEXT: v_or_b32_e32 v7, v3, v4 +; GFX8-NEXT: v_add_f32_e32 v5, v5, v1 +; GFX8-NEXT: v_add_f32_e32 v6, v6, v2 +; GFX8-NEXT: v_cvt_f16_f32_e32 v5, v5 +; GFX8-NEXT: v_cvt_f16_f32_e32 v6, v6 +; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v5 +; GFX8-NEXT: v_or_b32_e32 v3, v6, v3 +; GFX8-NEXT: ds_cmpst_rtn_b32 v5, v0, v7, v3 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v5 +; GFX8-NEXT: v_cvt_f32_f16_e32 v3, v5 +; GFX8-NEXT: v_cvt_f32_f16_e32 v4, v4 +; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, v5, v7 +; GFX8-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX8-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_cbranch_execnz .LBB15_1 +; GFX8-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX8-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(3) %ptr, <2 x half> %val seq_cst + ret void +} + +define <2 x bfloat> @lds_atomic_fadd_ret_v2bf16(ptr addrspace(3) %ptr, <2 x bfloat> %val) { +; VI-LABEL: lds_atomic_fadd_ret_v2bf16: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: s_mov_b32 m0, -1 +; VI-NEXT: ds_read_b32 v2, v0 +; VI-NEXT: s_mov_b64 s[6:7], 0 +; VI-NEXT: v_lshlrev_b32_e32 v3, 16, v1 +; VI-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; VI-NEXT: .LBB16_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v4, v2 +; VI-NEXT: v_lshlrev_b32_e32 v2, 16, v4 +; VI-NEXT: v_and_b32_e32 v5, 0xffff0000, v4 +; VI-NEXT: v_add_f32_e32 v2, v2, v3 +; VI-NEXT: v_add_f32_e32 v5, v5, v1 +; VI-NEXT: v_bfe_u32 v6, v2, 16, 1 +; VI-NEXT: v_bfe_u32 v8, v5, 16, 1 +; VI-NEXT: v_add_u32_e32 v6, vcc, v6, v2 +; VI-NEXT: v_add_u32_e32 v8, vcc, v8, v5 +; VI-NEXT: v_add_u32_e32 v6, vcc, 0x7fff, v6 +; VI-NEXT: v_add_u32_e32 v8, vcc, 0x7fff, v8 +; VI-NEXT: v_or_b32_e32 v9, 0x400000, v5 +; VI-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; VI-NEXT: v_or_b32_e32 v7, 0x400000, v2 +; VI-NEXT: v_cmp_u_f32_e64 s[4:5], v2, v2 +; VI-NEXT: v_cndmask_b32_e32 v5, v8, v9, vcc +; VI-NEXT: v_cndmask_b32_e64 v2, v6, v7, s[4:5] +; VI-NEXT: v_lshrrev_b32_e32 v5, 16, v5 +; VI-NEXT: v_alignbit_b32 v2, v5, v2, 16 +; VI-NEXT: ds_cmpst_rtn_b32 v2, v0, v4, v2 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v2, v4 +; VI-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; VI-NEXT: s_andn2_b64 exec, exec, s[6:7] +; VI-NEXT: s_cbranch_execnz .LBB16_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[6:7] +; VI-NEXT: v_mov_b32_e32 v0, v2 +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: lds_atomic_fadd_ret_v2bf16: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: ds_read_b32 v2, v0 +; GFX9-NEXT: s_mov_b64 s[6:7], 0 +; GFX9-NEXT: v_lshlrev_b32_e32 v3, 16, v1 +; GFX9-NEXT: s_movk_i32 s8, 0x7fff +; GFX9-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; GFX9-NEXT: s_mov_b32 s9, 0x7060302 +; GFX9-NEXT: .LBB16_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 16, v4 +; GFX9-NEXT: v_and_b32_e32 v5, 0xffff0000, v4 +; GFX9-NEXT: v_add_f32_e32 v2, v2, v3 +; GFX9-NEXT: v_add_f32_e32 v5, v5, v1 +; GFX9-NEXT: v_bfe_u32 v6, v2, 16, 1 +; GFX9-NEXT: v_bfe_u32 v8, v5, 16, 1 +; GFX9-NEXT: v_or_b32_e32 v7, 0x400000, v2 +; GFX9-NEXT: v_or_b32_e32 v9, 0x400000, v5 +; GFX9-NEXT: v_add3_u32 v6, v6, v2, s8 +; GFX9-NEXT: v_add3_u32 v8, v8, v5, s8 +; GFX9-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; GFX9-NEXT: v_cmp_u_f32_e64 s[4:5], v2, v2 +; GFX9-NEXT: v_cndmask_b32_e64 v2, v6, v7, s[4:5] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v8, v9, vcc +; GFX9-NEXT: v_perm_b32 v2, v5, v2, s9 +; GFX9-NEXT: ds_cmpst_rtn_b32 v2, v0, v4, v2 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v2, v4 +; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX9-NEXT: s_cbranch_execnz .LBB16_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX9-NEXT: v_mov_b32_e32 v0, v2 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX7-LABEL: lds_atomic_fadd_ret_v2bf16: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: s_mov_b32 m0, -1 +; GFX7-NEXT: ds_read_b32 v3, v0 +; GFX7-NEXT: v_mov_b32_e32 v4, v1 +; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 +; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 +; GFX7-NEXT: s_mov_b64 s[4:5], 0 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v3 +; GFX7-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 +; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX7-NEXT: .LBB16_1: ; %atomicrmw.start +; GFX7-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 +; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v1 +; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v3 +; GFX7-NEXT: v_lshrrev_b32_e32 v1, 16, v1 +; GFX7-NEXT: v_add_f32_e32 v6, v6, v2 +; GFX7-NEXT: v_add_f32_e32 v5, v5, v4 +; GFX7-NEXT: v_alignbit_b32 v1, v1, v3, 16 +; GFX7-NEXT: v_lshrrev_b32_e32 v3, 16, v6 +; GFX7-NEXT: v_alignbit_b32 v3, v3, v5, 16 +; GFX7-NEXT: ds_cmpst_rtn_b32 v3, v0, v1, v3 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_cmp_eq_u32_e32 vcc, v3, v1 +; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v3 +; GFX7-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX7-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_cbranch_execnz .LBB16_1 +; GFX7-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX7-NEXT: v_mov_b32_e32 v0, v3 +; GFX7-NEXT: s_setpc_b64 s[30:31] +; +; GFX8-LABEL: lds_atomic_fadd_ret_v2bf16: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: ds_read_b32 v3, v0 +; GFX8-NEXT: v_mov_b32_e32 v4, v1 +; GFX8-NEXT: v_mul_f32_e32 v4, 1.0, v4 +; GFX8-NEXT: v_mul_f32_e32 v2, 1.0, v2 +; GFX8-NEXT: s_mov_b64 s[4:5], 0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_and_b32_e32 v1, 0xffff0000, v3 +; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX8-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 +; GFX8-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX8-NEXT: .LBB16_1: ; %atomicrmw.start +; GFX8-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX8-NEXT: v_mul_f32_e32 v1, 1.0, v1 +; GFX8-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; GFX8-NEXT: v_and_b32_e32 v6, 0xffff0000, v1 +; GFX8-NEXT: v_and_b32_e32 v5, 0xffff0000, v3 +; GFX8-NEXT: v_lshrrev_b32_e32 v1, 16, v1 +; GFX8-NEXT: v_add_f32_e32 v6, v6, v2 +; GFX8-NEXT: v_add_f32_e32 v5, v5, v4 +; GFX8-NEXT: v_alignbit_b32 v1, v1, v3, 16 +; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v6 +; GFX8-NEXT: v_alignbit_b32 v3, v3, v5, 16 +; GFX8-NEXT: ds_cmpst_rtn_b32 v3, v0, v1, v3 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, v3, v1 +; GFX8-NEXT: v_and_b32_e32 v1, 0xffff0000, v3 +; GFX8-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX8-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_cbranch_execnz .LBB16_1 +; GFX8-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX8-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX8-NEXT: v_mov_b32_e32 v0, v3 +; GFX8-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(3) %ptr, <2 x bfloat> %val seq_cst + ret <2 x bfloat> %result +} + +define void @lds_atomic_fadd_noret_v2bf16(ptr addrspace(3) %ptr, <2 x bfloat> %val) { +; VI-LABEL: lds_atomic_fadd_noret_v2bf16: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: s_mov_b32 m0, -1 +; VI-NEXT: ds_read_b32 v3, v0 +; VI-NEXT: s_mov_b64 s[6:7], 0 +; VI-NEXT: v_lshlrev_b32_e32 v2, 16, v1 +; VI-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; VI-NEXT: .LBB17_1: ; %atomicrmw.start +; VI-NEXT: ; =>This Inner Loop Header: Depth=1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v3 +; VI-NEXT: v_and_b32_e32 v5, 0xffff0000, v3 +; VI-NEXT: v_add_f32_e32 v4, v4, v2 +; VI-NEXT: v_add_f32_e32 v5, v5, v1 +; VI-NEXT: v_bfe_u32 v6, v4, 16, 1 +; VI-NEXT: v_bfe_u32 v8, v5, 16, 1 +; VI-NEXT: v_add_u32_e32 v6, vcc, v6, v4 +; VI-NEXT: v_add_u32_e32 v8, vcc, v8, v5 +; VI-NEXT: v_add_u32_e32 v6, vcc, 0x7fff, v6 +; VI-NEXT: v_add_u32_e32 v8, vcc, 0x7fff, v8 +; VI-NEXT: v_or_b32_e32 v9, 0x400000, v5 +; VI-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; VI-NEXT: v_or_b32_e32 v7, 0x400000, v4 +; VI-NEXT: v_cmp_u_f32_e64 s[4:5], v4, v4 +; VI-NEXT: v_cndmask_b32_e32 v5, v8, v9, vcc +; VI-NEXT: v_cndmask_b32_e64 v4, v6, v7, s[4:5] +; VI-NEXT: v_lshrrev_b32_e32 v5, 16, v5 +; VI-NEXT: v_alignbit_b32 v4, v5, v4, 16 +; VI-NEXT: ds_cmpst_rtn_b32 v4, v0, v3, v4 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 +; VI-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; VI-NEXT: v_mov_b32_e32 v3, v4 +; VI-NEXT: s_andn2_b64 exec, exec, s[6:7] +; VI-NEXT: s_cbranch_execnz .LBB17_1 +; VI-NEXT: ; %bb.2: ; %atomicrmw.end +; VI-NEXT: s_or_b64 exec, exec, s[6:7] +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: lds_atomic_fadd_noret_v2bf16: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: ds_read_b32 v3, v0 +; GFX9-NEXT: s_mov_b64 s[6:7], 0 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 16, v1 +; GFX9-NEXT: s_movk_i32 s8, 0x7fff +; GFX9-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; GFX9-NEXT: s_mov_b32 s9, 0x7060302 +; GFX9-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_lshlrev_b32_e32 v4, 16, v3 +; GFX9-NEXT: v_and_b32_e32 v5, 0xffff0000, v3 +; GFX9-NEXT: v_add_f32_e32 v4, v4, v2 +; GFX9-NEXT: v_add_f32_e32 v5, v5, v1 +; GFX9-NEXT: v_bfe_u32 v6, v4, 16, 1 +; GFX9-NEXT: v_bfe_u32 v8, v5, 16, 1 +; GFX9-NEXT: v_or_b32_e32 v7, 0x400000, v4 +; GFX9-NEXT: v_or_b32_e32 v9, 0x400000, v5 +; GFX9-NEXT: v_add3_u32 v6, v6, v4, s8 +; GFX9-NEXT: v_add3_u32 v8, v8, v5, s8 +; GFX9-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 +; GFX9-NEXT: v_cmp_u_f32_e64 s[4:5], v4, v4 +; GFX9-NEXT: v_cndmask_b32_e64 v4, v6, v7, s[4:5] +; GFX9-NEXT: v_cndmask_b32_e32 v5, v8, v9, vcc +; GFX9-NEXT: v_perm_b32 v4, v5, v4, s9 +; GFX9-NEXT: ds_cmpst_rtn_b32 v4, v0, v3, v4 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 +; GFX9-NEXT: s_or_b64 s[6:7], vcc, s[6:7] +; GFX9-NEXT: v_mov_b32_e32 v3, v4 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[6:7] +; GFX9-NEXT: s_cbranch_execnz .LBB17_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX7-LABEL: lds_atomic_fadd_noret_v2bf16: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: s_mov_b32 m0, -1 +; GFX7-NEXT: ds_read_b32 v4, v0 +; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 +; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 +; GFX7-NEXT: s_mov_b64 s[4:5], 0 +; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v4 +; GFX7-NEXT: v_lshlrev_b32_e32 v4, 16, v4 +; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX7-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX7-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 +; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v4 +; GFX7-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; GFX7-NEXT: v_add_f32_e32 v6, v6, v2 +; GFX7-NEXT: v_add_f32_e32 v5, v5, v1 +; GFX7-NEXT: v_alignbit_b32 v3, v3, v4, 16 +; GFX7-NEXT: v_lshrrev_b32_e32 v4, 16, v6 +; GFX7-NEXT: v_alignbit_b32 v4, v4, v5, 16 +; GFX7-NEXT: ds_cmpst_rtn_b32 v4, v0, v3, v4 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 +; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v4 +; GFX7-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7-NEXT: v_lshlrev_b32_e32 v4, 16, v4 +; GFX7-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_cbranch_execnz .LBB17_1 +; GFX7-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX7-NEXT: s_setpc_b64 s[30:31] +; +; GFX8-LABEL: lds_atomic_fadd_noret_v2bf16: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX8-NEXT: s_mov_b32 m0, -1 +; GFX8-NEXT: ds_read_b32 v4, v0 +; GFX8-NEXT: v_mul_f32_e32 v1, 1.0, v1 +; GFX8-NEXT: v_mul_f32_e32 v2, 1.0, v2 +; GFX8-NEXT: s_mov_b64 s[4:5], 0 +; GFX8-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_and_b32_e32 v3, 0xffff0000, v4 +; GFX8-NEXT: v_lshlrev_b32_e32 v4, 16, v4 +; GFX8-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 +; GFX8-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX8-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX8-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; GFX8-NEXT: v_mul_f32_e32 v4, 1.0, v4 +; GFX8-NEXT: v_and_b32_e32 v6, 0xffff0000, v3 +; GFX8-NEXT: v_and_b32_e32 v5, 0xffff0000, v4 +; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v3 +; GFX8-NEXT: v_add_f32_e32 v6, v6, v2 +; GFX8-NEXT: v_add_f32_e32 v5, v5, v1 +; GFX8-NEXT: v_alignbit_b32 v3, v3, v4, 16 +; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v6 +; GFX8-NEXT: v_alignbit_b32 v4, v4, v5, 16 +; GFX8-NEXT: ds_cmpst_rtn_b32 v4, v0, v3, v4 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 +; GFX8-NEXT: v_and_b32_e32 v3, 0xffff0000, v4 +; GFX8-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX8-NEXT: v_lshlrev_b32_e32 v4, 16, v4 +; GFX8-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_cbranch_execnz .LBB17_1 +; GFX8-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX8-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX8-NEXT: s_setpc_b64 s[30:31] + %result = atomicrmw fadd ptr addrspace(3) %ptr, <2 x bfloat> %val seq_cst + ret void +} + +!0 = !{} diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f32-system.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f32-system.ll new file mode 100644 index 000000000000..8bbbcd16cb1a --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f32-system.ll @@ -0,0 +1,3717 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX803 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX906 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX908 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX90A %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX940 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX10 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX11 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX12 %s + +;--------------------------------------------------------------------- +; atomicrmw xchg +;--------------------------------------------------------------------- + +; xchg is supported over PCIe, so no expansion is necessary +define float @test_atomicrmw_xchg_f32_global_system(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_xchg_f32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast float [[VALUE]] to i32 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[TMP1]] seq_cst, align 4 +; COMMON-NEXT: [[RES:%.*]] = bitcast i32 [[TMP2]] to float +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, float %value seq_cst + ret float %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define float @test_atomicrmw_xchg_f32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_xchg_f32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast float [[VALUE]] to i32 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[TMP1]] seq_cst, align 4 +; COMMON-NEXT: [[RES:%.*]] = bitcast i32 [[TMP2]] to float +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret float %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define float @test_atomicrmw_xchg_f32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_xchg_f32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast float [[VALUE]] to i32 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[TMP1]] seq_cst, align 4 +; COMMON-NEXT: [[RES:%.*]] = bitcast i32 [[TMP2]] to float +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define float @test_atomicrmw_xchg_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_xchg_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast float [[VALUE]] to i32 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[TMP1]] seq_cst, align 4 +; COMMON-NEXT: [[RES:%.*]] = bitcast i32 [[TMP2]] to float +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +;--------------------------------------------------------------------- +; atomicrmw fadd +;--------------------------------------------------------------------- + +define float @test_atomicrmw_fadd_f32_global_system(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4 +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0:![0-9]+]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz(ptr addrspace(1) %ptr, float %value) #0 { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic(ptr addrspace(1) %ptr, float %value) #1 { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz(ptr addrspace(1) %ptr, float %value) #0 { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic(ptr addrspace(1) %ptr, float %value) #1 { +; GFX803-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret float [[TMP5]] +; +; GFX906-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RES]] +; +; GFX10-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret float [[TMP5]] +; +; GFX11-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; +; GFX12-LABEL: define float @test_atomicrmw_fadd_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +;--------------------------------------------------------------------- +; atomicrmw fadd (no return) +;--------------------------------------------------------------------- + +define void @test_atomicrmw_fadd_noret_f32_global_system(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4 +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz(ptr addrspace(1) %ptr, float %value) #0 { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_daz( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic(ptr addrspace(1) %ptr, float %value) #1 { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f32_dynamic( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz(ptr addrspace(1) %ptr, float %value) #0 { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR1]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic(ptr addrspace(1) %ptr, float %value) #1 { +; GFX803-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX803-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret void +; +; GFX906-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX906-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret void +; +; GFX908-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], float [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]], !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX10-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX10-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret void +; +; GFX11-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; +; GFX12-LABEL: define void @test_atomicrmw_fadd_noret_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR2]] { +; GFX12-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret void +} + +;--------------------------------------------------------------------- +; atomicrmw fsub +;--------------------------------------------------------------------- + +define float @test_atomicrmw_fsub_f32_global_system(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fsub_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmax +;--------------------------------------------------------------------- + +define float @test_atomicrmw_fmax_f32_global_system(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmax_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmin +;--------------------------------------------------------------------- + +define float @test_atomicrmw_fmin_f32_global_system(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, float %value) { +; COMMON-LABEL: define float @test_atomicrmw_fmin_f32_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[LOADED]], float [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret float [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret float %res +} + +attributes #0 = { "denormal-fp-mode-f32"="preserve-sign,preserve-sign" } +attributes #1 = { "denormal-fp-mode-f32"="dynamic,dynamic" } + +!0 = !{} +;. +; GFX940: [[META0]] = !{} +;. diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f64-system.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f64-system.ll new file mode 100644 index 000000000000..e1890da15b0c --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-f64-system.ll @@ -0,0 +1,1685 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX803 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX906 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX908 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX90A %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX940 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX10 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX11 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX12 %s + +;--------------------------------------------------------------------- +; atomicrmw xchg +;--------------------------------------------------------------------- + +; xchg is supported over PCIe, so no expansion is necessary +define double @test_atomicrmw_xchg_f64_global_system(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_xchg_f64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast double [[VALUE]] to i64 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[TMP1]] seq_cst, align 8 +; COMMON-NEXT: [[RES:%.*]] = bitcast i64 [[TMP2]] to double +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, double %value seq_cst + ret double %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define double @test_atomicrmw_xchg_f64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_xchg_f64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast double [[VALUE]] to i64 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[TMP1]] seq_cst, align 8 +; COMMON-NEXT: [[RES:%.*]] = bitcast i64 [[TMP2]] to double +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret double %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define double @test_atomicrmw_xchg_f64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_xchg_f64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast double [[VALUE]] to i64 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[TMP1]] seq_cst, align 8 +; COMMON-NEXT: [[RES:%.*]] = bitcast i64 [[TMP2]] to double +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define double @test_atomicrmw_xchg_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_xchg_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = bitcast double [[VALUE]] to i64 +; COMMON-NEXT: [[TMP2:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[TMP1]] seq_cst, align 8 +; COMMON-NEXT: [[RES:%.*]] = bitcast i64 [[TMP2]] to double +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +;--------------------------------------------------------------------- +; atomicrmw fadd +;--------------------------------------------------------------------- + +define double @test_atomicrmw_fadd_f64_global_system(ptr addrspace(1) %ptr, double %value) { +; GFX803-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret double [[TMP5]] +; +; GFX906-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], double [[VALUE]] seq_cst, align 8 +; GFX940-NEXT: ret double [[RES]] +; +; GFX10-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret double [[TMP5]] +; +; GFX11-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; +; GFX12-LABEL: define double @test_atomicrmw_fadd_f64_global_system( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; GFX803-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret double [[TMP5]] +; +; GFX906-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], double [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0:![0-9]+]] +; GFX940-NEXT: ret double [[RES]] +; +; GFX10-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret double [[TMP5]] +; +; GFX11-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; +; GFX12-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; GFX803-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret double [[TMP5]] +; +; GFX906-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], double [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret double [[RES]] +; +; GFX10-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret double [[TMP5]] +; +; GFX11-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; +; GFX12-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; GFX803-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX803-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret double [[TMP5]] +; +; GFX906-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX906-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], double [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret double [[RES]] +; +; GFX10-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX10-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret double [[TMP5]] +; +; GFX11-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; +; GFX12-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; GFX12-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz(ptr addrspace(1) %ptr, double %value) #0 { +; GFX803-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX803-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret double [[TMP5]] +; +; GFX906-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX906-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], double [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret double [[RES]] +; +; GFX10-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX10-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret double [[TMP5]] +; +; GFX11-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; +; GFX12-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_daz( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; GFX12-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic(ptr addrspace(1) %ptr, double %value) #1 { +; GFX803-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX803-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX803-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX803-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX803: atomicrmw.start: +; GFX803-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX803-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX803-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX803-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX803-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX803-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX803-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX803-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX803-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX803: atomicrmw.end: +; GFX803-NEXT: ret double [[TMP5]] +; +; GFX906-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX906-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX906-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX906-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX906: atomicrmw.start: +; GFX906-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX906-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX906-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX906-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX906-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX906-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX906-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX906-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX906-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX906: atomicrmw.end: +; GFX906-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX908-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX90A-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX940-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX940-NEXT: [[RES:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR]], double [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; GFX940-NEXT: ret double [[RES]] +; +; GFX10-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX10-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX10-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX10-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX10: atomicrmw.start: +; GFX10-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX10-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX10-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX10-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX10-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX10-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX10-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX10-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX10-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX10: atomicrmw.end: +; GFX10-NEXT: ret double [[TMP5]] +; +; GFX11-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX11-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; +; GFX12-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_f64_dynamic( +; GFX12-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; GFX12-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; GFX12-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX12: atomicrmw.start: +; GFX12-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX12-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; GFX12-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX12-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX12-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; GFX12-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX12-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX12-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX12-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX12: atomicrmw.end: +; GFX12-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP3:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP5]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[NEWLOADED]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP3:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP5]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[NEWLOADED]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP3:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP5]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[NEWLOADED]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP3:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP5]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[NEWLOADED]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz(ptr addrspace(1) %ptr, double %value) #0 { +; COMMON-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP3:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP5]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[NEWLOADED]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic(ptr addrspace(1) %ptr, double %value) #1 { +; COMMON-LABEL: define double @test_atomicrmw_fadd_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP3:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP3]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP1]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP1]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP5]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[NEWLOADED]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +;--------------------------------------------------------------------- +; atomicrmw fsub +;--------------------------------------------------------------------- + +define double @test_atomicrmw_fsub_f64_global_system(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP9:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP9]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[TMP5]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP9:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP9]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[TMP5]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP9:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP9]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[TMP5]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fsub_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP2:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub double [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: store double [[NEW]], ptr addrspace(5) [[TMP2]], align 8 +; COMMON-NEXT: [[TMP9:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP4]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP2]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP2]]) +; COMMON-NEXT: [[TMP6:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP7:%.*]] = insertvalue { double, i1 } poison, double [[TMP6]], 0 +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } [[TMP7]], i1 [[TMP9]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP8]], 1 +; COMMON-NEXT: [[TMP5]] = extractvalue { double, i1 } [[TMP8]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmax +;--------------------------------------------------------------------- + +define double @test_atomicrmw_fmax_f64_global_system(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmax_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.maxnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmin +;--------------------------------------------------------------------- + +define double @test_atomicrmw_fmin_f64_global_system(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i64 [[NEWLOADED]] to double +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, double %value) { +; COMMON-LABEL: define double @test_atomicrmw_fmin_f64_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP3:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP4:%.*]] = alloca double, align 8, addrspace(5) +; COMMON-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call double @llvm.minnum.f64(double [[LOADED]], double [[VALUE]]) +; COMMON-NEXT: [[TMP5:%.*]] = addrspacecast ptr addrspace(1) [[PTR]] to ptr +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: store double [[LOADED]], ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: store double [[TMP2]], ptr addrspace(5) [[TMP4]], align 8 +; COMMON-NEXT: [[TMP10:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 8, ptr [[TMP5]], ptr addrspace(5) [[TMP3]], ptr addrspace(5) [[TMP4]], i32 5, i32 5) +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP4]]) +; COMMON-NEXT: [[TMP7:%.*]] = load double, ptr addrspace(5) [[TMP3]], align 8 +; COMMON-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[TMP3]]) +; COMMON-NEXT: [[TMP8:%.*]] = insertvalue { double, i1 } poison, double [[TMP7]], 0 +; COMMON-NEXT: [[TMP9:%.*]] = insertvalue { double, i1 } [[TMP8]], i1 [[TMP10]], 1 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { double, i1 } [[TMP9]], 1 +; COMMON-NEXT: [[TMP6]] = extractvalue { double, i1 } [[TMP9]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret double [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, double %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret double %res +} + +attributes #0 = { "denormal-fp-mode"="preserve-sign,preserve-sign" } +attributes #1 = { "denormal-fp-mode"="dynamic,dynamic" } + +!0 = !{} +;. +; GFX940: [[META0]] = !{} +;. diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i32-system.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i32-system.ll new file mode 100644 index 000000000000..b711b9fe4edf --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i32-system.ll @@ -0,0 +1,828 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX803 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX906 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX908 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX90A %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX940 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX10 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX11 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX12 %s + +;--------------------------------------------------------------------- +; atomicrmw xchg +;--------------------------------------------------------------------- + +; xchg is supported over PCIe, so no expansion is necessary +define i32 @test_atomicrmw_xchg_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xchg_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i32 @test_atomicrmw_xchg_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xchg_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0:![0-9]+]] +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i32 @test_atomicrmw_xchg_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xchg_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i32 @test_atomicrmw_xchg_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xchg_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw add +;--------------------------------------------------------------------- + +; add is supported over PCIe, so no expansion is necessary +define i32 @test_atomicrmw_add_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_add_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +; add is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i32 @test_atomicrmw_add_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_add_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +; add is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i32 @test_atomicrmw_add_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_add_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +; add is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i32 @test_atomicrmw_add_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_add_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw sub +;--------------------------------------------------------------------- + +; expansion is necessary, sub is not supported over PCIe +define i32 @test_atomicrmw_sub_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_sub_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_sub_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_sub_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_sub_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_sub_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_sub_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_sub_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw and +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_and_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_and_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_and_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_and_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_and_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_and_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_and_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_and_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw nand +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported +define i32 @test_atomicrmw_nand_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_nand_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i32 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_nand_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_nand_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i32 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_nand_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_nand_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i32 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_nand_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_nand_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i32 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw or +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_or_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_or_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_or_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_or_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_or_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_or_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_or_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_or_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw xor +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_xor_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xor_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_xor_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xor_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_xor_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xor_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_xor_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_xor_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw max +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_max_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_max_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_max_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_max_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_max_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_max_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_max_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_max_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw min +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_min_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_min_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_min_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_min_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_min_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_min_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_min_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_min_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw umax +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_umax_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umax_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_umax_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umax_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_umax_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umax_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_umax_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umax_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw umin +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_umin_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umin_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_umin_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umin_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_umin_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umin_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_umin_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_umin_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i32 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i32 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i32 [[LOADED]], i32 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[LOADED]], i32 [[NEW]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i32, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw uinc_wrap +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_uinc_wrap_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_uinc_wrap_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_uinc_wrap_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_uinc_wrap_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_uinc_wrap_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_uinc_wrap_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_uinc_wrap_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_uinc_wrap_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +;--------------------------------------------------------------------- +; atomicrmw udec_wrap +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i32 @test_atomicrmw_udec_wrap_i32_global_system(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_udec_wrap_i32_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4 +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i32 %value seq_cst + ret i32 %res +} + +define i32 @test_atomicrmw_udec_wrap_i32_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_udec_wrap_i32_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i32 %res +} + +define i32 @test_atomicrmw_udec_wrap_i32_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_udec_wrap_i32_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @test_atomicrmw_udec_wrap_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i32 %value) { +; COMMON-LABEL: define i32 @test_atomicrmw_udec_wrap_i32_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i32 [[VALUE]] seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i32 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i32 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +!0 = !{} +;. +; GFX803: [[META0]] = !{} +;. +; GFX906: [[META0]] = !{} +;. +; GFX908: [[META0]] = !{} +;. +; GFX90A: [[META0]] = !{} +;. +; GFX940: [[META0]] = !{} +;. +; GFX10: [[META0]] = !{} +;. +; GFX11: [[META0]] = !{} +;. +; GFX12: [[META0]] = !{} +;. +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GFX10: {{.*}} +; GFX11: {{.*}} +; GFX12: {{.*}} +; GFX803: {{.*}} +; GFX906: {{.*}} +; GFX908: {{.*}} +; GFX90A: {{.*}} +; GFX940: {{.*}} diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i64-system.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i64-system.ll new file mode 100644 index 000000000000..d67bf2e450b8 --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-i64-system.ll @@ -0,0 +1,828 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX803 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX906 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX908 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX90A %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX940 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX10 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX11 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX12 %s + +;--------------------------------------------------------------------- +; atomicrmw xchg +;--------------------------------------------------------------------- + +; xchg is supported over PCIe, so no expansion is necessary +define i64 @test_atomicrmw_xchg_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xchg_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i64 @test_atomicrmw_xchg_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xchg_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0:![0-9]+]] +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i64 @test_atomicrmw_xchg_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xchg_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i64 @test_atomicrmw_xchg_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xchg_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw xchg ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw xchg ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw add +;--------------------------------------------------------------------- + +; add is supported over PCIe, so no expansion is necessary +define i64 @test_atomicrmw_add_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_add_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +; add is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i64 @test_atomicrmw_add_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_add_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +; add is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i64 @test_atomicrmw_add_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_add_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +; add is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +define i64 @test_atomicrmw_add_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_add_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[RES]] +; + %res = atomicrmw add ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw sub +;--------------------------------------------------------------------- + +; expansion is necessary, sub is not supported over PCIe +define i64 @test_atomicrmw_sub_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_sub_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_sub_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_sub_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_sub_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_sub_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_sub_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_sub_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw sub ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw sub ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw and +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_and_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_and_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_and_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_and_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_and_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_and_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_and_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_and_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw and ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw and ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw nand +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported +define i64 @test_atomicrmw_nand_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_nand_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i64 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_nand_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_nand_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i64 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_nand_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_nand_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i64 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_nand_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_nand_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = and i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = xor i64 [[TMP2]], -1 +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw nand ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw or +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_or_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_or_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_or_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_or_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_or_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_or_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_or_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_or_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw or ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw xor +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_xor_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xor_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_xor_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xor_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_xor_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xor_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_xor_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_xor_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw max +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_max_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_max_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_max_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_max_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_max_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_max_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_max_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_max_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sgt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw max ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw min +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_min_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_min_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_min_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_min_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_min_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_min_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_min_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_min_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp sle i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw min ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw umax +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_umax_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umax_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_umax_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umax_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_umax_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umax_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_umax_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umax_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umax ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw umin +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_umin_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umin_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_umin_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umin_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_umin_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umin_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_umin_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_umin_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load i64, ptr addrspace(1) [[PTR]], align 8 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi i64 [ [[TMP1]], [[TMP0:%.*]] ], [ [[NEWLOADED:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = icmp ule i64 [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[NEW:%.*]] = select i1 [[TMP2]], i64 [[LOADED]], i64 [[VALUE]] +; COMMON-NEXT: [[TMP3:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[LOADED]], i64 [[NEW]] seq_cst seq_cst, align 8 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP3]], 1 +; COMMON-NEXT: [[NEWLOADED]] = extractvalue { i64, i1 } [[TMP3]], 0 +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw umin ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw uinc_wrap +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_uinc_wrap_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_uinc_wrap_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_uinc_wrap_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_uinc_wrap_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_uinc_wrap_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_uinc_wrap_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_uinc_wrap_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_uinc_wrap_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw uinc_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw uinc_wrap ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +;--------------------------------------------------------------------- +; atomicrmw udec_wrap +;--------------------------------------------------------------------- + +; expansion is necessary, operation not supported over PCIe +define i64 @test_atomicrmw_udec_wrap_i64_global_system(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_udec_wrap_i64_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8 +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i64 %value seq_cst + ret i64 %res +} + +define i64 @test_atomicrmw_udec_wrap_i64_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_udec_wrap_i64_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret i64 %res +} + +define i64 @test_atomicrmw_udec_wrap_i64_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_udec_wrap_i64_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +define i64 @test_atomicrmw_udec_wrap_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, i64 %value) { +; COMMON-LABEL: define i64 @test_atomicrmw_udec_wrap_i64_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], i64 [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[NEWLOADED:%.*]] = atomicrmw udec_wrap ptr addrspace(1) [[PTR]], i64 [[VALUE]] seq_cst, align 8, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; COMMON-NEXT: ret i64 [[NEWLOADED]] +; + %res = atomicrmw udec_wrap ptr addrspace(1) %ptr, i64 %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i64 %res +} + +!0 = !{} +;. +; GFX803: [[META0]] = !{} +;. +; GFX906: [[META0]] = !{} +;. +; GFX908: [[META0]] = !{} +;. +; GFX90A: [[META0]] = !{} +;. +; GFX940: [[META0]] = !{} +;. +; GFX10: [[META0]] = !{} +;. +; GFX11: [[META0]] = !{} +;. +; GFX12: [[META0]] = !{} +;. +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GFX10: {{.*}} +; GFX11: {{.*}} +; GFX12: {{.*}} +; GFX803: {{.*}} +; GFX906: {{.*}} +; GFX908: {{.*}} +; GFX90A: {{.*}} +; GFX940: {{.*}} diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll index 8c7d8f5be88e..337e51f9a912 100644 --- a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll @@ -1750,7 +1750,7 @@ define void @test_atomicrmw_fadd_f32_global_no_use_unsafe_structfp(ptr addrspace ; CI-NEXT: br label [[ATOMICRMW_START:%.*]] ; CI: atomicrmw.start: ; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; CI-NEXT: [[NEW:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[LOADED]], float [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6:[0-9]+]] +; CI-NEXT: [[NEW:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[LOADED]], float [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9:[0-9]+]] ; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 ; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 ; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("wavefront") monotonic monotonic, align 4 @@ -1766,7 +1766,7 @@ define void @test_atomicrmw_fadd_f32_global_no_use_unsafe_structfp(ptr addrspace ; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] ; GFX9: atomicrmw.start: ; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; GFX9-NEXT: [[NEW:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[LOADED]], float [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6:[0-9]+]] +; GFX9-NEXT: [[NEW:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[LOADED]], float [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9:[0-9]+]] ; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 ; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 ; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("wavefront") monotonic monotonic, align 4 @@ -1803,7 +1803,7 @@ define double @test_atomicrmw_fadd_f64_global_unsafe_strictfp(ptr addrspace(1) % ; CI-NEXT: br label [[ATOMICRMW_START:%.*]] ; CI: atomicrmw.start: ; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; CI-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] +; CI-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9]] ; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 ; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 ; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] syncscope("wavefront") monotonic monotonic, align 8 @@ -1819,7 +1819,7 @@ define double @test_atomicrmw_fadd_f64_global_unsafe_strictfp(ptr addrspace(1) % ; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] ; GFX9: atomicrmw.start: ; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; GFX9-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] +; GFX9-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9]] ; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 ; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 ; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] syncscope("wavefront") monotonic monotonic, align 8 @@ -1835,7 +1835,7 @@ define double @test_atomicrmw_fadd_f64_global_unsafe_strictfp(ptr addrspace(1) % ; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] ; GFX908: atomicrmw.start: ; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; GFX908-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6:[0-9]+]] +; GFX908-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9:[0-9]+]] ; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 ; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 ; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] syncscope("wavefront") monotonic monotonic, align 8 @@ -1859,7 +1859,7 @@ define double @test_atomicrmw_fadd_f64_global_unsafe_strictfp(ptr addrspace(1) % ; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] ; GFX11: atomicrmw.start: ; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; GFX11-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6:[0-9]+]] +; GFX11-NEXT: [[NEW:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[LOADED]], double [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9:[0-9]+]] ; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 ; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 ; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] syncscope("wavefront") monotonic monotonic, align 8 @@ -1880,7 +1880,7 @@ define float @test_atomicrmw_fadd_f32_local_strictfp(ptr addrspace(3) %ptr, floa ; CI-NEXT: br label [[ATOMICRMW_START:%.*]] ; CI: atomicrmw.start: ; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; CI-NEXT: [[NEW:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[LOADED]], float [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] +; CI-NEXT: [[NEW:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[LOADED]], float [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9]] ; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 ; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 ; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 @@ -2102,7 +2102,7 @@ define bfloat @test_atomicrmw_fadd_bf16_global_system_align4(ptr addrspace(1) %p define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bfloat %value) #2 { ; ALL-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; ALL-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6:[0-9]+]] +; ALL-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR9:[0-9]+]] ; ALL-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; ALL-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; ALL-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -2115,7 +2115,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; ALL-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; ALL-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; ALL-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; ALL-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] +; ALL-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR9]] ; ALL-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; ALL-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; ALL-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] @@ -2259,6 +2259,2197 @@ define bfloat @test_atomicrmw_fadd_bf16_flat_system_align4(ptr %ptr, bfloat %val ret bfloat %res } +define void @test_atomicrmw_fadd_f32_global_system_noret(ptr addrspace(1) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_global_system_noret( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_global_system_noret( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_global_system_noret( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_global_system_noret( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_global_system_noret( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_global_system_noret( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic + ret void +} + +define float @test_atomicrmw_fadd_f32_global_system_ret(ptr addrspace(1) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_global_system_ret( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_global_system_ret( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_global_system_ret( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_global_system_ret( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_global_system_ret( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_global_system_ret( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic + ret float %ret +} + +define void @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0:![0-9]+]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define float @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret float %ret +} + +define void @test_atomicrmw_fadd_f32_daz_global_system_noret(ptr addrspace(1) %ptr, float %value) #3 { +; CI-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic + ret void +} + +define float @test_atomicrmw_fadd_f32_daz_global_system_ret(ptr addrspace(1) %ptr, float %value) #3 { +; CI-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic + ret float %ret +} + +define void @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) #3 { +; CI-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define float @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) #3 { +; CI-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_daz_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret float %ret +} + +define void @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) #4 { +; CI-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define float @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, float %value) #4 { +; CI-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(1) [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret float %ret +} + +define void @test_atomicrmw_fadd_f32_local_noret(ptr addrspace(3) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_local_noret( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(3) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_local_noret( +; GFX9-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_local_noret( +; GFX908-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_local_noret( +; GFX90A-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_local_noret( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_local_noret( +; GFX11-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(3) %ptr, float %value monotonic + ret void +} + +define float @test_atomicrmw_fadd_f32_local_ret(ptr addrspace(3) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_local_ret( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(3) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_local_ret( +; GFX9-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX9-NEXT: ret float [[RET]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_local_ret( +; GFX908-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX908-NEXT: ret float [[RET]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_local_ret( +; GFX90A-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX90A-NEXT: ret float [[RET]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_local_ret( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_local_ret( +; GFX11-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4 +; GFX11-NEXT: ret float [[RET]] +; + %ret = atomicrmw fadd ptr addrspace(3) %ptr, float %value monotonic + ret float %ret +} + +define void @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(3) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0:![0-9]+]] +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0:![0-9]+]] +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0:![0-9]+]] +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_local_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0:![0-9]+]] +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(3) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define float @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(3) [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX9-NEXT: ret float [[RET]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX908-NEXT: ret float [[RET]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX90A-NEXT: ret float [[RET]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_local_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX11-NEXT: ret float [[RET]] +; + %ret = atomicrmw fadd ptr addrspace(3) %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret float %ret +} + +define void @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret(ptr addrspace(1) %ptr, double %value) #5 { +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret( +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8 +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, double %value monotonic + ret void +} + +define double @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret(ptr addrspace(1) %ptr, double %value) #5 { +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret double [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret( +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8 +; GFX940-NEXT: ret double [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, double %value monotonic + ret double %ret +} + +define void @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, double %value) #5 { +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(1) %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define double @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, double %value) #5 { +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret double [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret double [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(1) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(1) %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret double %ret +} + +define void @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret(ptr addrspace(3) %ptr, double %value) #5 { +; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic + ret void +} + +define double @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret(ptr addrspace(3) %ptr, double %value) #5 { +; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret double [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic + ret double %ret +} + +define void @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr, double %value) #5 { +; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define double @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr, double %value) #5 { +; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret double [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret double %ret +} + +define void @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode(ptr %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define float @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode(ptr %ptr, float %value) { +; CI-LABEL: @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; CI-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret float [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret float [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret float [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret float [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr [[PTR:%.*]], float [[VALUE:%.*]] monotonic, align 4, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret float [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f32_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr %ptr, float %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret float %ret +} + +define void @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode(ptr %ptr, double %value) #5 { +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void +; + %unused = atomicrmw fadd ptr %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret void +} + +define double @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode(ptr %ptr, double %value) #5 { +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret double [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX90A-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX90A: atomicrmw.start: +; GFX90A-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX90A-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX90A-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX90A-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX90A-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX90A-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX90A-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX90A-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX90A-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX90A: atomicrmw.end: +; GFX90A-NEXT: ret double [[TMP5]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret double [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_flat_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] +; + %ret = atomicrmw fadd ptr %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 + ret double %ret +} + +define void @test_atomicrmw_fadd_f32_region_noret(ptr addrspace(2) %ptr, float %value) { +; ALL-LABEL: @test_atomicrmw_fadd_f32_region_noret( +; ALL-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(2) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(2) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(2) %ptr, float %value monotonic + ret void +} + +define float @test_atomicrmw_fadd_f32_region_ret(ptr addrspace(2) %ptr, float %value) { +; ALL-LABEL: @test_atomicrmw_fadd_f32_region_ret( +; ALL-NEXT: [[TMP1:%.*]] = load float, ptr addrspace(2) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast float [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast float [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(2) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] monotonic monotonic, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to float +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret float [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(2) %ptr, float %value monotonic + ret float %ret +} + +define void @test_atomicrmw_fadd_f64_region_noret(ptr addrspace(2) %ptr, double %value) { +; ALL-LABEL: @test_atomicrmw_fadd_f64_region_noret( +; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(2) [[PTR:%.*]], align 8 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(2) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %unused = atomicrmw fadd ptr addrspace(2) %ptr, double %value monotonic + ret void +} + +define double @test_atomicrmw_fadd_f64_region_ret(ptr addrspace(2) %ptr, double %value) { +; ALL-LABEL: @test_atomicrmw_fadd_f64_region_ret( +; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(2) [[PTR:%.*]], align 8 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(2) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret double [[TMP5]] +; + %ret = atomicrmw fadd ptr addrspace(2) %ptr, double %value monotonic + ret double %ret +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_flat_agent(ptr %ptr, <2 x half> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2f16_flat_agent( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr %ptr, <2 x half> %value syncscope("agent") seq_cst + ret <2 x half> %res +} + +define void @test_atomicrmw_fadd_v2f16_flat_agent_noret(ptr %ptr, <2 x half> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2f16_flat_agent_noret( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %res = atomicrmw fadd ptr %ptr, <2 x half> %value syncscope("agent") seq_cst + ret void +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_agent(ptr addrspace(1) %ptr, <2 x half> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2f16_global_agent( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value syncscope("agent") seq_cst + ret <2 x half> %res +} + +define void @test_atomicrmw_fadd_v2f16_flat_global_noret(ptr addrspace(1) %ptr, <2 x half> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2f16_flat_global_noret( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value syncscope("agent") seq_cst + ret void +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_local_agent(ptr addrspace(3) %ptr, <2 x half> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2f16_local_agent( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(3) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(3) %ptr, <2 x half> %value syncscope("agent") seq_cst + ret <2 x half> %res +} + +define void @test_atomicrmw_fadd_v2f16_flat_local_noret(ptr addrspace(3) %ptr, <2 x half> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2f16_flat_local_noret( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(3) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(3) %ptr, <2 x half> %value syncscope("agent") seq_cst + ret void +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_flat_agent(ptr %ptr, <2 x bfloat> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2bf16_flat_agent( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr %ptr, <2 x bfloat> %value syncscope("agent") seq_cst + ret <2 x bfloat> %res +} + +define void @test_atomicrmw_fadd_v2bf16_flat_agent_noret(ptr %ptr, <2 x bfloat> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2bf16_flat_agent_noret( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %res = atomicrmw fadd ptr %ptr, <2 x bfloat> %value syncscope("agent") seq_cst + ret void +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_agent(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2bf16_global_agent( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value syncscope("agent") seq_cst + ret <2 x bfloat> %res +} + +define void @test_atomicrmw_fadd_v2bf16_flat_global_noret(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2bf16_flat_global_noret( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value syncscope("agent") seq_cst + ret void +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_local_agent(ptr addrspace(3) %ptr, <2 x bfloat> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2bf16_local_agent( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(3) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(3) %ptr, <2 x bfloat> %value syncscope("agent") seq_cst + ret <2 x bfloat> %res +} + +define void @test_atomicrmw_fadd_v2bf16_flat_local_noret(ptr addrspace(3) %ptr, <2 x bfloat> %value) { +; ALL-LABEL: @test_atomicrmw_fadd_v2bf16_flat_local_noret( +; ALL-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(3) [[PTR:%.*]], align 4 +; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] +; ALL: atomicrmw.start: +; ALL-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; ALL-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE:%.*]] +; ALL-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; ALL-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] syncscope("agent") seq_cst seq_cst, align 4 +; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; ALL-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; ALL: atomicrmw.end: +; ALL-NEXT: ret void +; + %res = atomicrmw fadd ptr addrspace(3) %ptr, <2 x bfloat> %value syncscope("agent") seq_cst + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #1 = { strictfp "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #2 = { strictfp } +attributes #3 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" } +attributes #4 = { "denormal-fp-math-f32"="dynamic,dynamic" } +attributes #5 = { "denormal-fp-math"="dynamic,dynamic" } + +!0 = !{} diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2bf16-system.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2bf16-system.ll new file mode 100644 index 000000000000..01a23097008c --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2bf16-system.ll @@ -0,0 +1,859 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX803 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX906 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX908 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX90A %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX940 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX10 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX11 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX12 %s + +;--------------------------------------------------------------------- +; TODO: atomicrmw xchg +;--------------------------------------------------------------------- + +; ; xchg is supported over PCIe, so no expansion is necessary +; define <2 x bfloat> @test_atomicrmw_xchg_v2bf16_global_system(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst +; ret <2 x bfloat> %res +; } + +; ; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +; define <2 x bfloat> @test_atomicrmw_xchg_v2bf16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0 +; ret <2 x bfloat> %res +; } + +; ; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +; define <2 x bfloat> @test_atomicrmw_xchg_v2bf16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.remote.memory.access !0 +; ret <2 x bfloat> %res +; } + +; ; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +; define <2 x bfloat> @test_atomicrmw_xchg_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 +; ret <2 x bfloat> %res +; } + +;--------------------------------------------------------------------- +; atomicrmw fadd +;--------------------------------------------------------------------- + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2bf16_daz(ptr addrspace(1) %ptr, <2 x bfloat> %value) #0 { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2bf16_daz( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2bf16_dynamic(ptr addrspace(1) %ptr, <2 x bfloat> %value) #1 { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2bf16_dynamic( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz(ptr addrspace(1) %ptr, <2 x bfloat> %value) #0 { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR1]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic(ptr addrspace(1) %ptr, <2 x bfloat> %value) #1 { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fadd_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR2]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +;--------------------------------------------------------------------- +; atomicrmw fsub +;--------------------------------------------------------------------- + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fsub_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x bfloat> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x bfloat> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmax +;--------------------------------------------------------------------- + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmax_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.maxnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmin +;--------------------------------------------------------------------- + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x bfloat> %value) { +; COMMON-LABEL: define <2 x bfloat> @test_atomicrmw_fmin_v2bf16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x bfloat> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x bfloat>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x bfloat> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x bfloat> @llvm.minnum.v2bf16(<2 x bfloat> [[LOADED]], <2 x bfloat> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x bfloat> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x bfloat> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x bfloat> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x bfloat> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x bfloat> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x bfloat> %res +} + +attributes #0 = { "denormal-fp-mode"="preserve-sign,preserve-sign" } +attributes #1 = { "denormal-fp-mode"="dynamic,dynamic" } + +!0 = !{} +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GFX10: {{.*}} +; GFX11: {{.*}} +; GFX12: {{.*}} +; GFX803: {{.*}} +; GFX906: {{.*}} +; GFX908: {{.*}} +; GFX90A: {{.*}} +; GFX940: {{.*}} diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2f16-system.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2f16-system.ll new file mode 100644 index 000000000000..2a1824b0ca4a --- /dev/null +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-v2f16-system.ll @@ -0,0 +1,859 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx803 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX803 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX906 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX908 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX90A %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX940 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX10 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX11 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=atomic-expand %s | FileCheck -check-prefixes=COMMON,GFX12 %s + +;--------------------------------------------------------------------- +; TODO: atomicrmw xchg +;--------------------------------------------------------------------- + +; ; xchg is supported over PCIe, so no expansion is necessary +; define <2 x half> @test_atomicrmw_xchg_v2f16_global_system(ptr addrspace(1) %ptr, <2 x half> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x half> %value seq_cst +; ret <2 x half> %res +; } + +; ; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +; define <2 x half> @test_atomicrmw_xchg_v2f16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0 +; ret <2 x half> %res +; } + +; ; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +; define <2 x half> @test_atomicrmw_xchg_v2f16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.remote.memory.access !0 +; ret <2 x half> %res +; } + +; ; xchg is supported over PCIe, so no expansion is necessary. Metadata should be ignored. +; define <2 x half> @test_atomicrmw_xchg_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; %res = atomicrmw xchg ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 +; ret <2 x half> %res +; } + +;--------------------------------------------------------------------- +; atomicrmw fadd +;--------------------------------------------------------------------- + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2f16_daz(ptr addrspace(1) %ptr, <2 x half> %value) #0 { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2f16_daz( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR1:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2f16_dynamic(ptr addrspace(1) %ptr, <2 x half> %value) #1 { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access___denormal_fp_mode_v2f16_dynamic( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR2:[0-9]+]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz(ptr addrspace(1) %ptr, <2 x half> %value) #0 { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_daz( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR1]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic(ptr addrspace(1) %ptr, <2 x half> %value) #1 { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fadd_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access__denormal_mode_dynamic( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR2]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fadd <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fadd ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +;--------------------------------------------------------------------- +; atomicrmw fsub +;--------------------------------------------------------------------- + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fsub_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[NEW:%.*]] = fsub <2 x half> [[LOADED]], [[VALUE]] +; COMMON-NEXT: [[TMP2:%.*]] = bitcast <2 x half> [[NEW]] to i32 +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP3]], i32 [[TMP2]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; COMMON-NEXT: [[TMP5]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP5]] +; + %res = atomicrmw fsub ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmax +;--------------------------------------------------------------------- + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmax_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.maxnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmax ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +;--------------------------------------------------------------------- +; atomicrmw fmin +;--------------------------------------------------------------------- + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[RES:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[RES]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[RES]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access(ptr addrspace(1) %ptr, <2 x half> %value) { +; COMMON-LABEL: define <2 x half> @test_atomicrmw_fmin_v2f16_global_system__amdgpu_ignore_denormal_mode__amdgpu_no_fine_grained_memory__amdgpu_no_remote_memory_access( +; COMMON-SAME: ptr addrspace(1) [[PTR:%.*]], <2 x half> [[VALUE:%.*]]) #[[ATTR0]] { +; COMMON-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR]], align 4 +; COMMON-NEXT: br label [[ATOMICRMW_START:%.*]] +; COMMON: atomicrmw.start: +; COMMON-NEXT: [[LOADED:%.*]] = phi <2 x half> [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ] +; COMMON-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.minnum.v2f16(<2 x half> [[LOADED]], <2 x half> [[VALUE]]) +; COMMON-NEXT: [[TMP3:%.*]] = bitcast <2 x half> [[TMP2]] to i32 +; COMMON-NEXT: [[TMP4:%.*]] = bitcast <2 x half> [[LOADED]] to i32 +; COMMON-NEXT: [[TMP5:%.*]] = cmpxchg ptr addrspace(1) [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4 +; COMMON-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 +; COMMON-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 +; COMMON-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to <2 x half> +; COMMON-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; COMMON: atomicrmw.end: +; COMMON-NEXT: ret <2 x half> [[TMP6]] +; + %res = atomicrmw fmin ptr addrspace(1) %ptr, <2 x half> %value seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0, !amdgpu.ignore.denormal.mode !0 + ret <2 x half> %res +} + +attributes #0 = { "denormal-fp-mode"="preserve-sign,preserve-sign" } +attributes #1 = { "denormal-fp-mode"="dynamic,dynamic" } + +!0 = !{} +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GFX10: {{.*}} +; GFX11: {{.*}} +; GFX12: {{.*}} +; GFX803: {{.*}} +; GFX906: {{.*}} +; GFX908: {{.*}} +; GFX90A: {{.*}} +; GFX940: {{.*}} diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll index e32c218e9fe5..097d7b6ac577 100644 --- a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomicrmw-integer-ops-0-to-add-0.ll @@ -124,6 +124,16 @@ define i32 @test_atomicrmw_xor_0_global_system(ptr addrspace(1) %ptr) { } +define i32 @test_atomicrmw_or_0_global_system__metadata(ptr addrspace(1) %ptr) { +; CHECK-LABEL: define i32 @test_atomicrmw_or_0_global_system__metadata( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr addrspace(1) [[PTR]], i32 0 seq_cst, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw or ptr addrspace(1) %ptr, i32 0 seq_cst, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + !0 = !{} ;. ; CHECK: [[META0]] = !{} diff --git a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll index bfbe4899bedd..9ea2db86d7f3 100644 --- a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll +++ b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll @@ -182,4 +182,14 @@ entry: ret void } +; CHECK-LABEL: @atomicrmw_add_global_to_flat_preserve_amdgpu_md( +; CHECK-NEXT: %ret = atomicrmw add ptr addrspace(1) %global.ptr, i32 %y seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 +define i32 @atomicrmw_add_global_to_flat_preserve_amdgpu_md(ptr addrspace(1) %global.ptr, i32 %y) #0 { + %cast = addrspacecast ptr addrspace(1) %global.ptr to ptr + %ret = atomicrmw add ptr %cast, i32 %y seq_cst, align 4, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %ret +} + attributes #0 = { nounwind } + +!0 = !{} diff --git a/llvm/test/Transforms/Inline/AMDGPU/inline-atomicrmw-md-preserve.ll b/llvm/test/Transforms/Inline/AMDGPU/inline-atomicrmw-md-preserve.ll new file mode 100644 index 000000000000..ec7edd277dd7 --- /dev/null +++ b/llvm/test/Transforms/Inline/AMDGPU/inline-atomicrmw-md-preserve.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes=inline < %s | FileCheck %s +; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes='cgscc(inline)' < %s | FileCheck %s + +; Ensure that custom metadata survives inlining + +define i32 @atomic_xor(ptr addrspace(1) %ptr, i32 %val) { +; CHECK-LABEL: define i32 @atomic_xor( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VAL:%.*]]) { +; CHECK-NEXT: [[RES:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i32 [[VAL]] monotonic, align 4, !amdgpu.no.fine.grained.memory [[META0:![0-9]+]], !amdgpu.no.remote.memory.access [[META0]] +; CHECK-NEXT: ret i32 [[RES]] +; + %res = atomicrmw xor ptr addrspace(1) %ptr, i32 %val monotonic, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0 + ret i32 %res +} + +define i32 @caller(ptr addrspace(1) %ptr, i32 %val) { +; CHECK-LABEL: define i32 @caller( +; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]], i32 [[VAL:%.*]]) { +; CHECK-NEXT: [[RES_I:%.*]] = atomicrmw xor ptr addrspace(1) [[PTR]], i32 [[VAL]] monotonic, align 4, !amdgpu.no.fine.grained.memory [[META0]], !amdgpu.no.remote.memory.access [[META0]] +; CHECK-NEXT: ret i32 [[RES_I]] +; + %res = call i32 @atomic_xor(ptr addrspace(1) %ptr, i32 %val) + ret i32 %res +} + +!0 = !{} +;. +; CHECK: [[META0]] = !{} +;. -- GitLab From c69efcd54879835085cf03a09e1eec28dc80e1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Fri, 19 Apr 2024 15:55:24 -0700 Subject: [PATCH 053/357] [flang][cuda] Relax assumed size check on object with device attribute (#89466) Assumed size arrays are apparently allowed with attribute device. --- flang/lib/Semantics/check-declarations.cpp | 5 ----- flang/test/Semantics/cuf03.cuf | 3 +-- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index adbd21dfe6d4..6fcee96dd690 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -948,11 +948,6 @@ void CheckHelper::CheckObjectEntity( "Component '%s' with ATTRIBUTES(DEVICE) must also be allocatable"_err_en_US, symbol.name()); } - if (IsAssumedSizeArray(symbol)) { - messages_.Say( - "Object '%s' with ATTRIBUTES(DEVICE) may not be assumed size"_err_en_US, - symbol.name()); - } break; case common::CUDADataAttr::Managed: if (!IsAutomatic(symbol) && !IsAllocatable(symbol) && diff --git a/flang/test/Semantics/cuf03.cuf b/flang/test/Semantics/cuf03.cuf index 020a1720aa2e..472d53db7462 100644 --- a/flang/test/Semantics/cuf03.cuf +++ b/flang/test/Semantics/cuf03.cuf @@ -57,8 +57,7 @@ module m contains attributes(device) subroutine devsubr(n,da) integer, intent(in) :: n - !ERROR: Object 'da' with ATTRIBUTES(DEVICE) may not be assumed size - real, device :: da(*) + real, device :: da(*) ! ok real, managed :: ma(n) ! ok !WARNING: Pointer 'dp' may not be associated in a device subprogram real, device, pointer :: dp -- GitLab From f09f99ed329f58c79fba43abf5fc73a28a0e2055 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 19 Apr 2024 16:06:25 -0700 Subject: [PATCH 054/357] [RISCV] Add RISCVTuneProcessorModel to 'generic' CPU. NFC Remove hardcode GENERIC cpu from RISCVTargetDefEmitter.cpp. --- llvm/lib/Target/RISCV/RISCVProcessors.td | 2 +- llvm/utils/TableGen/RISCVTargetDefEmitter.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVProcessors.td b/llvm/lib/Target/RISCV/RISCVProcessors.td index f9a557e02bfe..3c86036e65fa 100644 --- a/llvm/lib/Target/RISCV/RISCVProcessors.td +++ b/llvm/lib/Target/RISCV/RISCVProcessors.td @@ -66,7 +66,7 @@ def GENERIC_RV64 : RISCVProcessorModel<"generic-rv64", GenericTuneInfo; // Support generic for compatibility with other targets. The triple will be used // to change to the appropriate rv32/rv64 version. -def : ProcessorModel<"generic", NoSchedModel, []>, GenericTuneInfo; +def GENERIC : RISCVTuneProcessorModel<"generic", NoSchedModel>, GenericTuneInfo; def ROCKET_RV32 : RISCVProcessorModel<"rocket-rv32", RocketModel, diff --git a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp index e57bc6fb507e..62916bd62c01 100644 --- a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp @@ -82,7 +82,6 @@ static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) { OS << "#ifndef TUNE_PROC\n" << "#define TUNE_PROC(ENUM, NAME)\n" << "#endif\n\n"; - OS << "TUNE_PROC(GENERIC, \"generic\")\n"; for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVTuneProcessorModel")) { -- GitLab From 11019be4cf75ff40d2da84094477ab5dac818c99 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 16:34:43 -0700 Subject: [PATCH 055/357] [test][sancov] Regenerate with update_test_checks (#89457) Prepare for #89458 --- .../SanitizerCoverage/inline-bool-flag.ll | 29 +++--- .../SanitizerCoverage/stack-depth.ll | 92 +++++++++++++++---- 2 files changed, 90 insertions(+), 31 deletions(-) diff --git a/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll b/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll index be8b6c8b95ce..1380e6ac090c 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll @@ -1,23 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4 ; Test -sanitizer-coverage-inline-bool-flag=1 ; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-bool-flag=1 -S | FileCheck %s -; CHECK: $foo = comdat nodeduplicate -; CHECK: @__sancov_gen_ = private global [1 x i1] zeroinitializer, section "__sancov_bools", comdat($foo), align 1{{$}} -; CHECK: @__start___sancov_bools = extern_weak hidden global i1 -; CHECK-NEXT: @__stop___sancov_bools = extern_weak hidden global i1 -; CHECK: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_bool_flag], section "llvm.metadata" -; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @__sancov_gen_], section "llvm.metadata" target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" +;. +; CHECK: @__sancov_lowest_stack = external thread_local(initialexec) global i64 +; CHECK: @__sancov_gen_ = private global [1 x i1] zeroinitializer, section "__sancov_bools", comdat($foo), align 1 +; CHECK: @__start___sancov_bools = extern_weak hidden global i1 +; CHECK: @__stop___sancov_bools = extern_weak hidden global i1 +; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @sancov.module_ctor_bool_flag, ptr @sancov.module_ctor_bool_flag }] +; CHECK: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_bool_flag], section "llvm.metadata" +; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @__sancov_gen_], section "llvm.metadata" +;. define void @foo() { -; CHECK-LABEL: @foo( +; CHECK-LABEL: define void @foo() comdat { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr @__sancov_gen_, align 1, !nosanitize ![[#EMPTY:]] +; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr @__sancov_gen_, align 1, !nosanitize [[META0:![0-9]+]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i1 [[TMP0]], false ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] ; CHECK: 2: -; CHECK-NEXT: store i1 true, ptr @__sancov_gen_, align 1, !nosanitize ![[#EMPTY:]] +; CHECK-NEXT: store i1 true, ptr @__sancov_gen_, align 1, !nosanitize [[META0]] ; CHECK-NEXT: br label [[TMP3]] ; CHECK: 3: ; CHECK-NEXT: ret void @@ -25,6 +29,9 @@ define void @foo() { entry: ret void } -; CHECK: call void @__sanitizer_cov_bool_flag_init(ptr @__start___sancov_bools, ptr @__stop___sancov_bools) -; CHECK: ![[#EMPTY]] = !{} +;. +; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind } +;. +; CHECK: [[META0]] = !{} +;. diff --git a/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll b/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll index 0e5eaae96d73..908bca6cdf74 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll @@ -1,43 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4 ; This check verifies that stack depth instrumentation works correctly. -; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 \ -; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s -; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 \ -; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ -; RUN: -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-stack-depth -S | FileCheck %s --check-prefixes=L1 +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-stack-depth -S -sanitizer-coverage-trace-pc-guard | FileCheck %s --check-prefixes=L3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; CHECK: @__sancov_lowest_stack = thread_local(initialexec) global i64 -1 @__sancov_lowest_stack = thread_local global i64 0, align 8 +;. +; L1: @__sancov_lowest_stack = thread_local(initialexec) global i64 -1, align 8 +;. +; L3: @__sancov_lowest_stack = thread_local(initialexec) global i64 -1, align 8 +; L3: @__sancov_gen_ = private global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($foo), align 4 +; L3: @__sancov_gen_.1 = private global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($bar), align 4 +; L3: @__sancov_gen_.2 = private global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($_ZTW21__sancov_lowest_stack), align 4 +; L3: @__start___sancov_guards = extern_weak hidden global i32 +; L3: @__stop___sancov_guards = extern_weak hidden global i32 +; L3: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @sancov.module_ctor_trace_pc_guard, ptr @sancov.module_ctor_trace_pc_guard }] +; L3: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_trace_pc_guard], section "llvm.metadata" +; L3: @llvm.compiler.used = appending global [3 x ptr] [ptr @__sancov_gen_, ptr @__sancov_gen_.1, ptr @__sancov_gen_.2], section "llvm.metadata" +;. define i32 @foo() { +; L1-LABEL: define i32 @foo() { +; L1-NEXT: entry: +; L1-NEXT: ret i32 7 +; +; L3-LABEL: define i32 @foo() comdat { +; L3-NEXT: entry: +; L3-NEXT: call void @__sanitizer_cov_trace_pc_guard(ptr @__sancov_gen_) #[[ATTR2:[0-9]+]] +; L3-NEXT: ret i32 7 +; entry: -; CHECK-LABEL: define i32 @foo -; CHECK-NOT: call ptr @llvm.frameaddress.p0(i32 0) -; CHECK-NOT: @__sancov_lowest_stack -; CHECK: ret i32 7 ret i32 7 } define i32 @bar() { +; L1-LABEL: define i32 @bar() { +; L1-NEXT: entry: +; L1-NEXT: [[TMP0:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; L1-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 +; L1-NEXT: [[TMP2:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0:![0-9]+]] +; L1-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] +; L1-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] +; L1: 4: +; L1-NEXT: store i64 [[TMP1]], ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0]] +; L1-NEXT: br label [[TMP5]] +; L1: 5: +; L1-NEXT: [[CALL:%.*]] = call i32 @foo() +; L1-NEXT: ret i32 [[CALL]] +; +; L3-LABEL: define i32 @bar() comdat { +; L3-NEXT: entry: +; L3-NEXT: call void @__sanitizer_cov_trace_pc_guard(ptr @__sancov_gen_.1) #[[ATTR2]] +; L3-NEXT: [[TMP0:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; L3-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 +; L3-NEXT: [[TMP2:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0:![0-9]+]] +; L3-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] +; L3-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] +; L3: 4: +; L3-NEXT: store i64 [[TMP1]], ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0]] +; L3-NEXT: br label [[TMP5]] +; L3: 5: +; L3-NEXT: [[CALL:%.*]] = call i32 @foo() +; L3-NEXT: ret i32 [[CALL]] +; entry: -; CHECK-LABEL: define i32 @bar -; CHECK: [[framePtr:%[^ \t]+]] = call ptr @llvm.frameaddress.p0(i32 0) -; CHECK: [[frameInt:%[^ \t]+]] = ptrtoint ptr [[framePtr]] to [[intType:i[0-9]+]] -; CHECK: [[lowest:%[^ \t]+]] = load [[intType]], ptr @__sancov_lowest_stack -; CHECK: [[cmp:%[^ \t]+]] = icmp ult [[intType]] [[frameInt]], [[lowest]] -; CHECK: br i1 [[cmp]], label %[[ifLabel:[^ \t]+]], label -; CHECK: [[ifLabel]]: -; CHECK: store [[intType]] [[frameInt]], ptr @__sancov_lowest_stack -; CHECK: %call = call i32 @foo() -; CHECK: ret i32 %call %call = call i32 @foo() ret i32 %call } define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() { +; L1-LABEL: define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() { +; L1-NEXT: ret ptr @__sancov_lowest_stack +; +; L3-LABEL: define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() comdat { +; L3-NEXT: call void @__sanitizer_cov_trace_pc_guard(ptr @__sancov_gen_.2) #[[ATTR2]] +; L3-NEXT: ret ptr @__sancov_lowest_stack +; ret ptr @__sancov_lowest_stack } +;. +; L1: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } +;. +; L3: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } +; L3: attributes #[[ATTR1:[0-9]+]] = { nounwind } +; L3: attributes #[[ATTR2]] = { nomerge } +;. +; L1: [[META0]] = !{} +;. +; L3: [[META0]] = !{} +;. -- GitLab From c8627e4e0c8ac453844638522b887ac7b7687672 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 19 Apr 2024 16:36:15 -0700 Subject: [PATCH 056/357] Revert "[lldb] Provide a better error message for missing symbols (#89433)" This reverts commit 08163cd9d82690e808c28515523b5fd0923d7b38. I accidentally broke the test while addressing review feedback. --- lldb/source/Expression/IRExecutionUnit.cpp | 4 +--- lldb/test/API/lang/cpp/constructors/TestCppConstructors.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 07df8c52a2a4..cb9bee8733e1 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -431,9 +431,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, } m_failed_lookups.clear(); - ss.PutCString( - "\nHint: The expression tried to call a function that is not present " - "in the target, perhaps because it was optimized out by the compiler."); + error.SetErrorString(ss.GetString()); return; diff --git a/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py b/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py index 140877adba73..6724bfc8ed78 100644 --- a/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py +++ b/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py @@ -47,7 +47,7 @@ class TestCase(TestBase): self.expect( "expr ClassWithDeletedDefaultCtor().value", error=True, - substrs=["Couldn't look up symbols:", "function missing"], + substrs=["Couldn't look up symbols:"], ) @skipIfWindows # Can't find operator new. -- GitLab From 6a35ee8077647b32626c3c41f9d9da4dae6670fc Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 19 Apr 2024 22:14:55 +0200 Subject: [PATCH 057/357] [lldb] Provide a better error message for missing symbols (#89433) This adds a hint to the missing symbols error message to make it easier to understand what this means to users. [Reapplies an earlier patch with a test fix.] --- lldb/source/Expression/IRExecutionUnit.cpp | 4 +++- lldb/test/API/lang/cpp/constructors/TestCppConstructors.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index cb9bee8733e1..07df8c52a2a4 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -431,7 +431,9 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, } m_failed_lookups.clear(); - + ss.PutCString( + "\nHint: The expression tried to call a function that is not present " + "in the target, perhaps because it was optimized out by the compiler."); error.SetErrorString(ss.GetString()); return; diff --git a/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py b/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py index 6724bfc8ed78..baf06e4c59fb 100644 --- a/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py +++ b/lldb/test/API/lang/cpp/constructors/TestCppConstructors.py @@ -47,7 +47,7 @@ class TestCase(TestBase): self.expect( "expr ClassWithDeletedDefaultCtor().value", error=True, - substrs=["Couldn't look up symbols:"], + substrs=["Couldn't look up symbols:", "function", "optimized out"], ) @skipIfWindows # Can't find operator new. -- GitLab From 7fcca112034f55c26e943c13fd0d57adfbe96705 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Sat, 20 Apr 2024 07:45:20 +0800 Subject: [PATCH 058/357] [clang-tidy] bugprone-lambda-function-name ignore macro in captures (#89076) --- .../bugprone/LambdaFunctionNameCheck.cpp | 14 +++++++++++--- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++ .../bugprone/lambda-function-name.cpp | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp index 5260a8b4ecb0..32f5edddfe80 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp @@ -8,7 +8,9 @@ #include "LambdaFunctionNameCheck.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" @@ -56,6 +58,8 @@ private: LambdaFunctionNameCheck::SourceRangeSet* SuppressMacroExpansions; }; +AST_MATCHER(CXXMethodDecl, isInLambda) { return Node.getParent()->isLambda(); } + } // namespace LambdaFunctionNameCheck::LambdaFunctionNameCheck(StringRef Name, @@ -69,9 +73,13 @@ void LambdaFunctionNameCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) { - // Match on PredefinedExprs inside a lambda. - Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"), - this); + Finder->addMatcher( + cxxMethodDecl(isInLambda(), + hasBody(forEachDescendant( + predefinedExpr(hasAncestor(cxxMethodDecl().bind("fn"))) + .bind("E"))), + equalsBoundNode("fn")), + this); } void LambdaFunctionNameCheck::registerPPCallbacks( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a457e6fcae94..9ef1d38d3c45 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -155,6 +155,10 @@ Changes in existing checks ` check to ignore code within unevaluated contexts, such as ``decltype``. +- Improved :doc:`bugprone-lambda-function-name` + check by ignoring ``__func__`` macro in lambda captures, initializers of + default parameters and nested function declarations. + - Improved :doc:`bugprone-non-zero-enum-to-bool-conversion ` check by eliminating false positives resulting from direct usage of bitwise operators diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp index 936ee87a856c..5c2bb5713239 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp @@ -19,6 +19,22 @@ void Positives() { // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] [] { EMBED_IN_ANOTHER_MACRO1; }(); // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + [] { + __func__; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + struct S { + void f() { + __func__; + [] { + __func__; + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + }(); + __func__; + } + }; + __func__; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + }(); } #define FUNC_MACRO_WITH_FILE_AND_LINE Foo(__func__, __FILE__, __LINE__) @@ -40,4 +56,7 @@ void Negatives() { [] { FUNC_MACRO_WITH_FILE_AND_LINE; }(); [] { FUNCTION_MACRO_WITH_FILE_AND_LINE; }(); [] { EMBED_IN_ANOTHER_MACRO2; }(); + + [] (const char* func = __func__) { func; }(); + [func=__func__] { func; }(); } -- GitLab From 777d2e54a9b69463a30c305a0d1a34fef90dbe93 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Fri, 19 Apr 2024 17:00:57 -0700 Subject: [PATCH 059/357] [memprof] Drop the trait parameter (NFC) (#89461) OnDiskIterableChainedHashTable::Create can default-contruct a trait object for us. We don't need to construct one on our own unless we need to customize something (like a version number). --- llvm/lib/ProfileData/InstrProfReader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index b05bad7d59ec..cefb6af12d00 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -1272,13 +1272,13 @@ Error IndexedMemProfReader::deserialize(const unsigned char *Start, MemProfFrameTable.reset(MemProfFrameHashTable::Create( /*Buckets=*/Start + FrameTableOffset, /*Payload=*/Start + FramePayloadOffset, - /*Base=*/Start, memprof::FrameLookupTrait())); + /*Base=*/Start)); if (Version >= memprof::Version2) MemProfCallStackTable.reset(MemProfCallStackHashTable::Create( /*Buckets=*/Start + CallStackTableOffset, /*Payload=*/Start + CallStackPayloadOffset, - /*Base=*/Start, memprof::CallStackLookupTrait())); + /*Base=*/Start)); #ifdef EXPENSIVE_CHECKS // Go through all the records and verify that CSId has been correctly -- GitLab From f3587d41064ce22330231baee1553b210777f3e3 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 17:01:18 -0700 Subject: [PATCH 060/357] [sancov] Apply branch weights when checking counters (#89458) It reduces instrumentation overhead by ~50%. --- .../Transforms/Instrumentation/SanitizerCoverage.cpp | 10 +++++++--- .../SanitizerCoverage/inline-bool-flag.ll | 3 ++- .../Instrumentation/SanitizerCoverage/stack-depth.ll | 6 ++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 17c1c4423842..239e7c602a54 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" @@ -979,8 +980,9 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, FunctionBoolArray->getValueType(), FunctionBoolArray, {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); auto Load = IRB.CreateLoad(Int1Ty, FlagPtr); - auto ThenTerm = - SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false); + auto ThenTerm = SplitBlockAndInsertIfThen( + IRB.CreateIsNull(Load), &*IP, false, + MDBuilder(IRB.getContext()).createBranchWeights(1, (1 << 20) - 1)); IRBuilder<> ThenIRB(ThenTerm); auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); Load->setNoSanitizeMetadata(); @@ -997,7 +999,9 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack); auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); - auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); + auto ThenTerm = SplitBlockAndInsertIfThen( + IsStackLower, &*IP, false, + MDBuilder(IRB.getContext()).createBranchWeights(1, (1 << 20) - 1)); IRBuilder<> ThenIRB(ThenTerm); auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); LowestStack->setNoSanitizeMetadata(); diff --git a/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll b/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll index 1380e6ac090c..a6d7ae67d845 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll @@ -19,7 +19,7 @@ define void @foo() { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr @__sancov_gen_, align 1, !nosanitize [[META0:![0-9]+]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i1 [[TMP0]], false -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]], !prof [[PROF1:![0-9]+]] ; CHECK: 2: ; CHECK-NEXT: store i1 true, ptr @__sancov_gen_, align 1, !nosanitize [[META0]] ; CHECK-NEXT: br label [[TMP3]] @@ -34,4 +34,5 @@ entry: ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind } ;. ; CHECK: [[META0]] = !{} +; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575} ;. diff --git a/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll b/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll index 908bca6cdf74..00547afd1b9e 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll @@ -43,7 +43,7 @@ define i32 @bar() { ; L1-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 ; L1-NEXT: [[TMP2:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0:![0-9]+]] ; L1-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] -; L1-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] +; L1-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]], !prof [[PROF1:![0-9]+]] ; L1: 4: ; L1-NEXT: store i64 [[TMP1]], ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0]] ; L1-NEXT: br label [[TMP5]] @@ -58,7 +58,7 @@ define i32 @bar() { ; L3-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64 ; L3-NEXT: [[TMP2:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0:![0-9]+]] ; L3-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] -; L3-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] +; L3-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]], !prof [[PROF1:![0-9]+]] ; L3: 4: ; L3-NEXT: store i64 [[TMP1]], ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0]] ; L3-NEXT: br label [[TMP5]] @@ -90,6 +90,8 @@ define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() { ; L3: attributes #[[ATTR2]] = { nomerge } ;. ; L1: [[META0]] = !{} +; L1: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575} ;. ; L3: [[META0]] = !{} +; L3: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575} ;. -- GitLab From c60aa430dc4085d276a630699323068bf36bd9d8 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 17:03:23 -0700 Subject: [PATCH 061/357] [NFCI][sanitizers][metadata] Exctract create{Unlikely,Likely}BranchWeights (#89464) We have a lot of repeated code with random constants. Particular values are not important, the one just needs to be bigger then another. UR_NONTAKEN_WEIGHT is selected as it's the most common one. --- llvm/include/llvm/IR/MDBuilder.h | 8 ++++++++ llvm/lib/IR/MDBuilder.cpp | 10 ++++++++++ llvm/lib/Transforms/IPO/CrossDSOCFI.cpp | 3 +-- llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 3 +-- .../Transforms/Instrumentation/AddressSanitizer.cpp | 4 ++-- .../Transforms/Instrumentation/DataFlowSanitizer.cpp | 4 ++-- .../Transforms/Instrumentation/HWAddressSanitizer.cpp | 8 ++++---- llvm/lib/Transforms/Instrumentation/KCFI.cpp | 3 +-- .../lib/Transforms/Instrumentation/MemorySanitizer.cpp | 4 ++-- .../Transforms/Instrumentation/SanitizerCoverage.cpp | 4 ++-- .../Instrumentation/AddressSanitizer/asan-funclet.ll | 2 +- llvm/test/Instrumentation/AddressSanitizer/basic.ll | 2 +- 12 files changed, 35 insertions(+), 20 deletions(-) diff --git a/llvm/include/llvm/IR/MDBuilder.h b/llvm/include/llvm/IR/MDBuilder.h index 39165453de16..3265589b7c8d 100644 --- a/llvm/include/llvm/IR/MDBuilder.h +++ b/llvm/include/llvm/IR/MDBuilder.h @@ -61,6 +61,14 @@ public: /// Return metadata containing two branch weights. MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight); + /// Return metadata containing two branch weights, with significant bias + /// towards `true` destination. + MDNode *createLikelyBranchWeights(); + + /// Return metadata containing two branch weights, with significant bias + /// towards `false` destination. + MDNode *createUnlikelyBranchWeights(); + /// Return metadata containing a number of branch weights. MDNode *createBranchWeights(ArrayRef Weights); diff --git a/llvm/lib/IR/MDBuilder.cpp b/llvm/lib/IR/MDBuilder.cpp index 2490b3012bdc..0bf41d7cc7c2 100644 --- a/llvm/lib/IR/MDBuilder.cpp +++ b/llvm/lib/IR/MDBuilder.cpp @@ -39,6 +39,16 @@ MDNode *MDBuilder::createBranchWeights(uint32_t TrueWeight, return createBranchWeights({TrueWeight, FalseWeight}); } +MDNode *MDBuilder::createLikelyBranchWeights() { + // Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp + return createBranchWeights((1U << 20) - 1, 1); +} + +MDNode *MDBuilder::createUnlikelyBranchWeights() { + // Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp + return createBranchWeights(1, (1U << 20) - 1); +} + MDNode *MDBuilder::createBranchWeights(ArrayRef Weights) { assert(Weights.size() >= 1 && "Need at least one branch weights!"); diff --git a/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp b/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp index 5cc8258a495a..91d445dfc4c7 100644 --- a/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp +++ b/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp @@ -139,8 +139,7 @@ void CrossDSOCFI::buildCFICheck(Module &M) { } bool CrossDSOCFI::runOnModule(Module &M) { - VeryLikelyWeights = - MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1); + VeryLikelyWeights = MDBuilder(M.getContext()).createLikelyBranchWeights(); if (M.getModuleFlag("Cross-DSO CFI") == nullptr) return false; buildCFICheck(M); diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index cf13c91a8677..e7a188e9431d 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -1196,8 +1196,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo, // function pointer to the devirtualized target. In case of a mismatch, // fall back to indirect call. if (DevirtCheckMode == WPDCheckMode::Fallback) { - MDNode *Weights = - MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1); + MDNode *Weights = MDBuilder(M.getContext()).createLikelyBranchWeights(); // Version the indirect call site. If the called value is equal to the // given callee, 'NewInst' will be executed, otherwise the original call // site will be executed. diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 26fedbfd65dd..9cc978dc6c16 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1817,7 +1817,7 @@ Instruction *AddressSanitizer::genAMDGPUReportBlock(IRBuilder<> &IRB, auto *Trm = SplitBlockAndInsertIfThen(ReportCond, &*IRB.GetInsertPoint(), false, - MDBuilder(*C).createBranchWeights(1, 100000)); + MDBuilder(*C).createUnlikelyBranchWeights()); Trm->getParent()->setName("asan.report"); if (Recover) @@ -1894,7 +1894,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns, // We use branch weights for the slow path check, to indicate that the slow // path is rarely taken. This seems to be the case for SPEC benchmarks. Instruction *CheckTerm = SplitBlockAndInsertIfThen( - Cmp, InsertBefore, false, MDBuilder(*C).createBranchWeights(1, 100000)); + Cmp, InsertBefore, false, MDBuilder(*C).createUnlikelyBranchWeights()); assert(cast(CheckTerm)->isUnconditional()); BasicBlock *NextBB = CheckTerm->getSuccessor(0); IRB.SetInsertPoint(CheckTerm); diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 9a2ec7618c1a..cdd891fc8948 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -1229,8 +1229,8 @@ bool DataFlowSanitizer::initializeModule(Module &M) { FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs, /*isVarArg=*/false); - ColdCallWeights = MDBuilder(*Ctx).createBranchWeights(1, 1000); - OriginStoreWeights = MDBuilder(*Ctx).createBranchWeights(1, 1000); + ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights(); + OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights(); return true; } diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 3890aa8ca6ee..865722d02598 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -911,7 +911,7 @@ HWAddressSanitizer::insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore, R.TagMismatchTerm = SplitBlockAndInsertIfThen( TagMismatch, InsertBefore, false, - MDBuilder(*C).createBranchWeights(1, 100000), &DTU, LI); + MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI); return R; } @@ -952,7 +952,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite, IRB.CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15)); Instruction *CheckFailTerm = SplitBlockAndInsertIfThen( OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover, - MDBuilder(*C).createBranchWeights(1, 100000), &DTU, LI); + MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI); IRB.SetInsertPoint(TCI.TagMismatchTerm); Value *PtrLowBits = IRB.CreateTrunc(IRB.CreateAnd(TCI.PtrLong, 15), Int8Ty); @@ -960,7 +960,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite, PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1)); Value *PtrLowBitsOOB = IRB.CreateICmpUGE(PtrLowBits, TCI.MemTag); SplitBlockAndInsertIfThen(PtrLowBitsOOB, TCI.TagMismatchTerm, false, - MDBuilder(*C).createBranchWeights(1, 100000), &DTU, + MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI, CheckFailTerm->getParent()); IRB.SetInsertPoint(TCI.TagMismatchTerm); @@ -969,7 +969,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite, Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr); Value *InlineTagMismatch = IRB.CreateICmpNE(TCI.PtrTag, InlineTag); SplitBlockAndInsertIfThen(InlineTagMismatch, TCI.TagMismatchTerm, false, - MDBuilder(*C).createBranchWeights(1, 100000), &DTU, + MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI, CheckFailTerm->getParent()); IRB.SetInsertPoint(CheckFailTerm); diff --git a/llvm/lib/Transforms/Instrumentation/KCFI.cpp b/llvm/lib/Transforms/Instrumentation/KCFI.cpp index b22e7f7fc0be..28dc1c02b661 100644 --- a/llvm/lib/Transforms/Instrumentation/KCFI.cpp +++ b/llvm/lib/Transforms/Instrumentation/KCFI.cpp @@ -71,8 +71,7 @@ PreservedAnalyses KCFIPass::run(Function &F, FunctionAnalysisManager &AM) { "compatible with -fsanitize=kcfi on this target")); IntegerType *Int32Ty = Type::getInt32Ty(Ctx); - MDNode *VeryUnlikelyWeights = - MDBuilder(Ctx).createBranchWeights(1, (1U << 20) - 1); + MDNode *VeryUnlikelyWeights = MDBuilder(Ctx).createUnlikelyBranchWeights(); Triple T(M.getTargetTriple()); for (CallInst *CI : KCFICalls) { diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index ee3531bbd68d..1d7d0356ea69 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1040,8 +1040,8 @@ void MemorySanitizer::initializeModule(Module &M) { OriginTy = IRB.getInt32Ty(); PtrTy = IRB.getPtrTy(); - ColdCallWeights = MDBuilder(*C).createBranchWeights(1, 1000); - OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000); + ColdCallWeights = MDBuilder(*C).createUnlikelyBranchWeights(); + OriginStoreWeights = MDBuilder(*C).createUnlikelyBranchWeights(); if (!CompileKernel) { if (TrackOrigins) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 239e7c602a54..b7d4da07da8c 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -982,7 +982,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, auto Load = IRB.CreateLoad(Int1Ty, FlagPtr); auto ThenTerm = SplitBlockAndInsertIfThen( IRB.CreateIsNull(Load), &*IP, false, - MDBuilder(IRB.getContext()).createBranchWeights(1, (1 << 20) - 1)); + MDBuilder(IRB.getContext()).createUnlikelyBranchWeights()); IRBuilder<> ThenIRB(ThenTerm); auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); Load->setNoSanitizeMetadata(); @@ -1001,7 +1001,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); auto ThenTerm = SplitBlockAndInsertIfThen( IsStackLower, &*IP, false, - MDBuilder(IRB.getContext()).createBranchWeights(1, (1 << 20) - 1)); + MDBuilder(IRB.getContext()).createUnlikelyBranchWeights()); IRBuilder<> ThenIRB(ThenTerm); auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); LowestStack->setNoSanitizeMetadata(); diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll index 6d40e2b7eaf9..62c0a24c60d7 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll @@ -580,5 +580,5 @@ ehcleanup: ; preds = %entry cleanupret from %0 unwind to caller } ;. -; CHECK-INLINE: [[PROF0]] = !{!"branch_weights", i32 1, i32 100000} +; CHECK-INLINE: [[PROF0]] = !{!"branch_weights", i32 1, i32 1048575} ;. diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic.ll b/llvm/test/Instrumentation/AddressSanitizer/basic.ll index 2064db5a0918..1aef8c03c9d3 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/basic.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/basic.ll @@ -218,4 +218,4 @@ define void @test_swifterror_3() sanitize_address { ; CHECK: attributes #[[#ATTR]] = { nounwind } ; PROF -; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 100000} +; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 1048575} -- GitLab From f35e1931bebedf80c13939eda9c5c0aa2c2c4f6a Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Fri, 19 Apr 2024 17:11:39 -0700 Subject: [PATCH 062/357] Revert "[flang][cuda] Use fir.cuda_deallocate for automatic deallocation (#89450)" This reverts commit 2a632d3d9f5c70db38c617b0816deb37ef722a7b. This has some implication on OpenACC postDeallocate action --- flang/include/flang/Lower/Allocatable.h | 4 +-- flang/lib/Lower/Allocatable.cpp | 12 ++++----- flang/lib/Lower/ConvertVariable.cpp | 5 ++-- flang/test/Lower/CUDA/cuda-allocatable.cuf | 30 ---------------------- 4 files changed, 8 insertions(+), 43 deletions(-) diff --git a/flang/include/flang/Lower/Allocatable.h b/flang/include/flang/Lower/Allocatable.h index e8738f0407e7..d3c16de377c1 100644 --- a/flang/include/flang/Lower/Allocatable.h +++ b/flang/include/flang/Lower/Allocatable.h @@ -55,14 +55,12 @@ void genDeallocateStmt(AbstractConverter &converter, void genDeallocateBox(AbstractConverter &converter, const fir::MutableBoxValue &box, mlir::Location loc, - const Fortran::semantics::Symbol *sym = nullptr, mlir::Value declaredTypeDesc = {}); /// Deallocate an allocatable if it is allocated at the end of its lifetime. void genDeallocateIfAllocated(AbstractConverter &converter, const fir::MutableBoxValue &box, - mlir::Location loc, - const Fortran::semantics::Symbol *sym = nullptr); + mlir::Location loc); /// Create a MutableBoxValue for an allocatable or pointer entity. /// If the variables is a local variable that is not a dummy, it will be diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 8e84ea2fc5d5..38f61528d7e2 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -859,20 +859,18 @@ genDeallocate(fir::FirOpBuilder &builder, void Fortran::lower::genDeallocateBox( Fortran::lower::AbstractConverter &converter, const fir::MutableBoxValue &box, mlir::Location loc, - const Fortran::semantics::Symbol *sym, mlir::Value declaredTypeDesc) { + mlir::Value declaredTypeDesc) { const Fortran::lower::SomeExpr *statExpr = nullptr; const Fortran::lower::SomeExpr *errMsgExpr = nullptr; ErrorManager errorManager; errorManager.init(converter, loc, statExpr, errMsgExpr); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - genDeallocate(builder, converter, loc, box, errorManager, declaredTypeDesc, - sym); + genDeallocate(builder, converter, loc, box, errorManager, declaredTypeDesc); } void Fortran::lower::genDeallocateIfAllocated( Fortran::lower::AbstractConverter &converter, - const fir::MutableBoxValue &box, mlir::Location loc, - const Fortran::semantics::Symbol *sym) { + const fir::MutableBoxValue &box, mlir::Location loc) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Value isAllocated = fir::factory::genIsAllocatedOrAssociatedTest(builder, loc, box); @@ -882,9 +880,9 @@ void Fortran::lower::genDeallocateIfAllocated( eleType.isa() && box.isPolymorphic()) { mlir::Value declaredTypeDesc = builder.create( loc, mlir::TypeAttr::get(eleType)); - genDeallocateBox(converter, box, loc, sym, declaredTypeDesc); + genDeallocateBox(converter, box, loc, declaredTypeDesc); } else { - genDeallocateBox(converter, box, loc, sym); + genDeallocateBox(converter, box, loc); } }) .end(); diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index c40435c0977c..2d2d9eba905b 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -916,14 +916,13 @@ static void instantiateLocal(Fortran::lower::AbstractConverter &converter, break; case VariableCleanUp::Deallocate: auto *converterPtr = &converter; - auto *sym = &var.getSymbol(); - converter.getFctCtx().attachCleanup([converterPtr, loc, exv, sym]() { + converter.getFctCtx().attachCleanup([converterPtr, loc, exv]() { const fir::MutableBoxValue *mutableBox = exv.getBoxOf(); assert(mutableBox && "trying to deallocate entity not lowered as allocatable"); Fortran::lower::genDeallocateIfAllocated(*converterPtr, *mutableBox, - loc, sym); + loc); }); } } diff --git a/flang/test/Lower/CUDA/cuda-allocatable.cuf b/flang/test/Lower/CUDA/cuda-allocatable.cuf index eff5f13669e9..251ff16a56c7 100644 --- a/flang/test/Lower/CUDA/cuda-allocatable.cuf +++ b/flang/test/Lower/CUDA/cuda-allocatable.cuf @@ -17,15 +17,6 @@ end subroutine ! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: %[[BOX_LOAD:.*]] = fir.load %[[BOX_DECL]]#1 : !fir.ref>>> -! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX_LOAD]] : (!fir.box>>) -> !fir.heap> -! CHECK: %[[ADDR_I64:.*]] = fir.convert %[[ADDR]] : (!fir.heap>) -> i64 -! CHECK: %[[C0:.*]] = arith.constant 0 : i64 -! CHECK: %[[NE_C0:.*]] = arith.cmpi ne, %[[ADDR_I64]], %[[C0]] : i64 -! CHECK: fir.if %[[NE_C0]] { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } - subroutine sub2() real, allocatable, managed :: a(:) integer :: istat @@ -46,10 +37,6 @@ end subroutine ! CHECK: %[[STAT:.*]] = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda, hasStat} -> i32 ! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref -! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } - subroutine sub3() integer, allocatable, pinned :: a(:,:) logical :: plog @@ -63,9 +50,6 @@ end subroutine ! CHECK: %[[PLOG_DECL:.*]]:2 = hlfir.declare %5 {uniq_name = "_QFsub3Eplog"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK-2: fir.call @_FortranAAllocatableSetBounds ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> pinned(%[[PLOG_DECL]]#1 : !fir.ref>) {cuda_attr = #fir.cuda} -> i32 -! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } subroutine sub4() real, allocatable, device :: a(:) @@ -81,9 +65,6 @@ end subroutine ! CHECK: fir.call @_FortranAAllocatableSetBounds ! CHECK: %[[STREAM:.*]] = fir.load %[[ISTREAM_DECL]]#0 : !fir.ref ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_DECL]]#1 : !fir.ref>>> stream(%[[STREAM]] : i32) {cuda_attr = #fir.cuda} -> i32 -! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } subroutine sub5() real, allocatable, device :: a(:) @@ -99,11 +80,6 @@ end subroutine ! CHECK: %[[LOAD_B:.*]] = fir.load %[[BOX_B_DECL]]#1 : !fir.ref>>> ! CHECK: fir.call @_FortranAAllocatableSetBounds ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_A_DECL]]#1 : !fir.ref>>> source(%[[LOAD_B]] : !fir.box>>) {cuda_attr = #fir.cuda} -> i32 -! CHECK: fir.if -! CHECK: fir.freemem -! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } subroutine sub6() real, allocatable, device :: a(:) @@ -119,9 +95,6 @@ end subroutine ! CHECK: %[[LOAD_B:.*]] = fir.load %[[BOX_B_DECL]]#1 : !fir.ref>>> ! CHECK: fir.call @_FortranAAllocatableApplyMold ! CHECK: %{{.*}} = fir.cuda_allocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_A_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } subroutine sub7() real, allocatable, device :: a(:) @@ -147,6 +120,3 @@ end subroutine ! CHECK: %[[ERR_BOX:.*]] = fir.embox %[[ERR_DECL]]#1 : (!fir.ref>) -> !fir.box> ! CHECK: %[[STAT:.*]] = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> errmsg(%15 : !fir.box>) {cuda_attr = #fir.cuda, hasStat} -> i32 ! CHECK: fir.store %[[STAT]] to %[[ISTAT_DECL]]#1 : !fir.ref -! CHECK: fir.if %{{.*}} { -! CHECK: %{{.*}} = fir.cuda_deallocate %[[BOX_DECL]]#1 : !fir.ref>>> {cuda_attr = #fir.cuda} -> i32 -! CHECK: } -- GitLab From b48ea2d394911efcc56880fde58f806282db1e8a Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 20 Apr 2024 02:34:50 +0200 Subject: [PATCH 063/357] Revert "[clang] CTAD: Fix require-clause is not transformed." (#89476) Reverts llvm/llvm-project#89378 Broke the windows premerge checks https://lab.llvm.org/buildbot/#/builders/271/builds/6788 --- clang/lib/Sema/SemaTemplate.cpp | 27 +++++++++---------- clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 +++- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 18 ------------- clang/test/SemaTemplate/deduction-guide.cpp | 28 -------------------- 4 files changed, 17 insertions(+), 61 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4bda31ba67c0..d4976f9d0d11 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2962,6 +2962,19 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getCanonicalTemplateArgument( Context.getInjectedTemplateArg(NewParam)); } + // Substitute new template parameters into requires-clause if present. + Expr *RequiresClause = + transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); + // FIXME: implement the is_deducible constraint per C++ + // [over.match.class.deduct]p3.3: + // ... and a constraint that is satisfied if and only if the arguments + // of A are deducible (see below) from the return type. + auto *FPrimeTemplateParamList = TemplateParameterList::Create( + Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), + AliasTemplate->getTemplateParameters()->getLAngleLoc(), + FPrimeTemplateParams, + AliasTemplate->getTemplateParameters()->getRAngleLoc(), + /*RequiresClause=*/RequiresClause); // To form a deduction guide f' from f, we leverage clang's instantiation // mechanism, we construct a template argument list where the template @@ -3007,20 +3020,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias( F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), Sema::CodeSynthesisContext::BuildingDeductionGuides)) { auto *GG = cast(FPrime); - // Substitute new template parameters into requires-clause if present. - Expr *RequiresClause = - transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); - // FIXME: implement the is_deducible constraint per C++ - // [over.match.class.deduct]p3.3: - // ... and a constraint that is satisfied if and only if the arguments - // of A are deducible (see below) from the return type. - auto *FPrimeTemplateParamList = TemplateParameterList::Create( - Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), - AliasTemplate->getTemplateParameters()->getLAngleLoc(), - FPrimeTemplateParams, - AliasTemplate->getTemplateParameters()->getRAngleLoc(), - /*RequiresClause=*/RequiresClause); - buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList, GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), GG->getTypeSourceInfo(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 98d5c7cb3a8a..3e6676f21c9b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2502,7 +2502,10 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, assert(Arg.getKind() == TemplateArgument::Type && "unexpected nontype template argument kind in template rewrite"); QualType NewT = Arg.getAsType(); - TLB.pushTrivial(SemaRef.Context, NewT, TL.getNameLoc()); + assert(isa(NewT) && + "type parm not rewritten to type parm"); + auto NewTL = TLB.push(NewT); + NewTL.setNameLoc(TL.getNameLoc()); return NewT; } diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 508a3a5da76a..6f04264a655a 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -289,21 +289,3 @@ using String = Array; // Verify no crash on constructing the aggregate deduction guides. String s("hello"); } // namespace test21 - -// GH89013 -namespace test22 { -class Base {}; -template -class Derived final : public Base {}; - -template -requires __is_base_of(Base, D) -struct Foo { - explicit Foo(D) {} -}; - -template -using AFoo = Foo>; - -AFoo a(Derived{}); -} // namespace test22 diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 29cc5a9b996f..58f08aa1eed6 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -260,31 +260,3 @@ AG ag = {1}; // CHECK: |-TemplateArgument type 'int' // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' - -template -requires (sizeof(D) == 4) -struct Foo { - Foo(D); -}; - -template -using AFoo = Foo>; -// Verify that the require-clause from the Foo deduction guide is transformed. -// The D occurrence should be rewritten to G. -// -// CHECK-LABEL: Dumping -// CHECK: FunctionTemplateDecl {{.*}} implicit -// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 U -// CHECK-NEXT: |-ParenExpr {{.*}} 'bool' -// CHECK-NEXT: | `-BinaryOperator {{.*}} 'bool' '==' -// CHECK-NEXT: | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'G' -// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'unsigned long' -// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 -// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (G) -> Foo>' -// CHECK-NEXT: | `-ParmVarDecl {{.*}} 'G' -// CHECK-NEXT: `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (G) -> Foo>' implicit_instantiation -// CHECK-NEXT: |-TemplateArgument type 'int' -// CHECK-NEXT: | `-BuiltinType {{.*}} 'int' -// CHECK-NEXT: `-ParmVarDecl {{.*}} 'G' - -AFoo aa(G{}); -- GitLab From c4a799b0566662a5d80543da0f720efc92899a59 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 17:42:17 -0700 Subject: [PATCH 064/357] [NFC][hwasan] Use DEBUG_TYPE instead of "hwasan" --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 865722d02598..a35f24447cc3 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -293,8 +293,8 @@ public: : M(M), SSI(SSI) { this->Recover = optOr(ClRecover, Recover); this->CompileKernel = optOr(ClEnableKhwasan, CompileKernel); - this->Rng = - ClRandomSkipRate.getNumOccurrences() ? M.createRNG("hwasan") : nullptr; + this->Rng = ClRandomSkipRate.getNumOccurrences() ? M.createRNG(DEBUG_TYPE) + : nullptr; initializeModule(); } -- GitLab From f2931182fc877e813974a5f53721f859bfb5b130 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Sat, 20 Apr 2024 00:49:47 +0000 Subject: [PATCH 065/357] Reland "[python] Bump Python minimum version to 3.8 (#78828)" This reverts commit 2dfa30d0ca6fb6991640a18e53401d82f567f8ff. This relands commit 0a6c74e21cc6750c843310ab35b47763cddaaf32. This patch originally caused a host of buildbot failures due to several buildbots not having the necessary python version. That was tracked in issue #83962, and all bots that failed in the first round have now been updated. This is an attempt to reland the patch to see if it sticks or if there are a number of long-running bots where this patch will cause failures. --- llvm/CMakeLists.txt | 4 ++-- llvm/docs/GettingStarted.rst | 8 ++++---- llvm/docs/GettingStartedVS.rst | 2 +- llvm/docs/ReleaseNotes.rst | 5 +++++ llvm/docs/TestingGuide.rst | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index d511376e18ba..505870154dbb 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -903,8 +903,8 @@ set(LLVM_PROFDATA_FILE "" CACHE FILEPATH "Profiling data file to use when compiling in order to improve runtime performance.") if(LLVM_INCLUDE_TESTS) - # Lit test suite requires at least python 3.6 - set(LLVM_MINIMUM_PYTHON_VERSION 3.6) + # All LLVM Python files should be compatible down to this minimum version. + set(LLVM_MINIMUM_PYTHON_VERSION 3.8) else() # FIXME: it is unknown if this is the actual minimum bound set(LLVM_MINIMUM_PYTHON_VERSION 3.0) diff --git a/llvm/docs/GettingStarted.rst b/llvm/docs/GettingStarted.rst index 7ecef78c405b..0a1913dca8aa 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -292,16 +292,16 @@ uses the package and provides other details. Package Version Notes =========================================================== ============ ========================================== `CMake `__ >=3.20.0 Makefile/workspace generator -`python `_ >=3.6 Automated test suite\ :sup:`1` +`python `_ >=3.8 Automated test suite\ :sup:`1` `zlib `_ >=1.2.3.4 Compression library\ :sup:`2` `GNU Make `_ 3.79, 3.79.1 Makefile/build processor\ :sup:`3` =========================================================== ============ ========================================== .. note:: - #. Only needed if you want to run the automated test suite. Python 3.8.0 - or later is needed on Windows if a substitute (virtual) drive is used - to access LLVM source code due to ``MAX_PATH`` limitations. + #. Only needed if you want to run the automated test suite in the + ``llvm/test`` directory, or if you plan to utilize any Python libraries, + utilities, or bindings. #. Optional, adds compression / uncompression capabilities to selected LLVM tools. #. Optional, you can use any other build tool supported by CMake. diff --git a/llvm/docs/GettingStartedVS.rst b/llvm/docs/GettingStartedVS.rst index a1eb88dccc9e..4b15272635fb 100644 --- a/llvm/docs/GettingStartedVS.rst +++ b/llvm/docs/GettingStartedVS.rst @@ -55,7 +55,7 @@ Visual Studio 2019 so separate installation is not required. If you do install CMake separately, Visual Studio 2022 will require CMake Version 3.21 or later. If you would like to run the LLVM tests you will need `Python -`_. Version 3.6 and newer are known to work. You can +`_. Version 3.8 and newer are known to work. You can install Python with Visual Studio 2019, from the Microsoft store or from the `Python web site `_. We recommend the latter since it allows you to adjust installation options. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 76ef6ceb9407..33b61688f787 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -47,6 +47,11 @@ Non-comprehensive list of changes in this release Update on required toolchains to build LLVM ------------------------------------------- +* The minimum Python version has been raised from 3.6 to 3.8 across all of LLVM. + This enables the use of many new Python features, aligning more closely with + modern Python best practices, and improves CI maintainability + See `#78828 `_ for more info. + Changes to the LLVM IR ---------------------- diff --git a/llvm/docs/TestingGuide.rst b/llvm/docs/TestingGuide.rst index e32e4d1e535a..3e3a722f1418 100644 --- a/llvm/docs/TestingGuide.rst +++ b/llvm/docs/TestingGuide.rst @@ -23,7 +23,7 @@ Requirements ============ In order to use the LLVM testing infrastructure, you will need all of the -software required to build LLVM, as well as `Python `_ 3.6 or +software required to build LLVM, as well as `Python `_ 3.8 or later. LLVM Testing Infrastructure Organization -- GitLab From 91c2e9c2d990473b7a3a1aad3e56a864a7481301 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 18:26:03 -0700 Subject: [PATCH 066/357] [NFC][SanCov] Pass DomTrees as const references They are not optional. --- .../Instrumentation/SanitizerCoverage.cpp | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index b7d4da07da8c..a7192d3d075d 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -204,12 +204,11 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { return Options; } -using DomTreeCallback = function_ref; -using PostDomTreeCallback = - function_ref; - class ModuleSanitizerCoverage { public: + using DomTreeCallback = function_ref; + using PostDomTreeCallback = + function_ref; ModuleSanitizerCoverage( const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), const SpecialCaseList *Allowlist = nullptr, @@ -289,11 +288,11 @@ PreservedAnalyses SanitizerCoveragePass::run(Module &M, ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), Blocklist.get()); auto &FAM = MAM.getResult(M).getManager(); - auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { - return &FAM.getResult(F); + auto DTCallback = [&FAM](Function &F) -> const DominatorTree & { + return FAM.getResult(F); }; - auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * { - return &FAM.getResult(F); + auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree & { + return FAM.getResult(F); }; if (!ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) return PreservedAnalyses::all(); @@ -519,29 +518,29 @@ bool ModuleSanitizerCoverage::instrumentModule( } // True if block has successors and it dominates all of them. -static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) { +static bool isFullDominator(const BasicBlock *BB, const DominatorTree &DT) { if (succ_empty(BB)) return false; return llvm::all_of(successors(BB), [&](const BasicBlock *SUCC) { - return DT->dominates(BB, SUCC); + return DT.dominates(BB, SUCC); }); } // True if block has predecessors and it postdominates all of them. static bool isFullPostDominator(const BasicBlock *BB, - const PostDominatorTree *PDT) { + const PostDominatorTree &PDT) { if (pred_empty(BB)) return false; return llvm::all_of(predecessors(BB), [&](const BasicBlock *PRED) { - return PDT->dominates(BB, PRED); + return PDT.dominates(BB, PRED); }); } static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, - const DominatorTree *DT, - const PostDominatorTree *PDT, + const DominatorTree &DT, + const PostDominatorTree &PDT, const SanitizerCoverageOptions &Options) { // Don't insert coverage for blocks containing nothing but unreachable: we // will never call __sanitizer_cov() for them, so counting them in @@ -569,17 +568,16 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, && !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor()); } - // Returns true iff From->To is a backedge. // A twist here is that we treat From->To as a backedge if // * To dominates From or // * To->UniqueSuccessor dominates From static bool IsBackEdge(BasicBlock *From, BasicBlock *To, - const DominatorTree *DT) { - if (DT->dominates(To, From)) + const DominatorTree &DT) { + if (DT.dominates(To, From)) return true; if (auto Next = To->getUniqueSuccessor()) - if (DT->dominates(Next, From)) + if (DT.dominates(Next, From)) return true; return false; } @@ -589,7 +587,7 @@ static bool IsBackEdge(BasicBlock *From, BasicBlock *To, // // Note that Cmp pruning is controlled by the same flag as the // BB pruning. -static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, +static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree &DT, const SanitizerCoverageOptions &Options) { if (!Options.NoPrune) if (CMP->hasOneUse()) @@ -641,8 +639,8 @@ void ModuleSanitizerCoverage::instrumentFunction( SmallVector Loads; SmallVector Stores; - const DominatorTree *DT = DTCallback(F); - const PostDominatorTree *PDT = PDTCallback(F); + const DominatorTree &DT = DTCallback(F); + const PostDominatorTree &PDT = PDTCallback(F); bool IsLeafFunc = true; for (auto &BB : F) { -- GitLab From 905f34eeca628da526293a21daa6a645012219c6 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 18:30:22 -0700 Subject: [PATCH 067/357] [NFCI][SanCov] Remove unused default arguments --- .../Instrumentation/SanitizerCoverage.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index a7192d3d075d..cd766dd3b42e 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -209,12 +209,13 @@ public: using DomTreeCallback = function_ref; using PostDomTreeCallback = function_ref; - ModuleSanitizerCoverage( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), - const SpecialCaseList *Allowlist = nullptr, - const SpecialCaseList *Blocklist = nullptr) - : Options(OverrideFromCL(Options)), Allowlist(Allowlist), + + ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options, + const SpecialCaseList *Allowlist, + const SpecialCaseList *Blocklist) + : Options(Options), Allowlist(Allowlist), Blocklist(Blocklist) {} + bool instrumentModule(Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); @@ -285,7 +286,7 @@ private: PreservedAnalyses SanitizerCoveragePass::run(Module &M, ModuleAnalysisManager &MAM) { - ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), + ModuleSanitizerCoverage ModuleSancov(OverrideFromCL(Options), Allowlist.get(), Blocklist.get()); auto &FAM = MAM.getResult(M).getManager(); auto DTCallback = [&FAM](Function &F) -> const DominatorTree & { -- GitLab From b0fe4d4ac3cbf0ef24c7a1b56e01472a19d746b4 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 18:45:40 -0700 Subject: [PATCH 068/357] [NFCI][SanCov] Remove redundant copt<> defaults --- .../Instrumentation/SanitizerCoverage.cpp | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index cd766dd3b42e..2cd2cc04a3c0 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -89,15 +89,14 @@ static cl::opt ClCoverageLevel( "sanitizer-coverage-level", cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, " "3: all blocks and critical edges"), - cl::Hidden, cl::init(0)); + cl::Hidden); static cl::opt ClTracePC("sanitizer-coverage-trace-pc", - cl::desc("Experimental pc tracing"), cl::Hidden, - cl::init(false)); + cl::desc("Experimental pc tracing"), cl::Hidden); static cl::opt ClTracePCGuard("sanitizer-coverage-trace-pc-guard", cl::desc("pc tracing with a guard"), - cl::Hidden, cl::init(false)); + cl::Hidden); // If true, we create a global variable that contains PCs of all instrumented // BBs, put this global into a named section, and pass this section's bounds @@ -107,38 +106,38 @@ static cl::opt ClTracePCGuard("sanitizer-coverage-trace-pc-guard", // inline-bool-flag. static cl::opt ClCreatePCTable("sanitizer-coverage-pc-table", cl::desc("create a static PC table"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters", cl::desc("increments 8-bit counter for every edge"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClInlineBoolFlag("sanitizer-coverage-inline-bool-flag", - cl::desc("sets a boolean flag for every edge"), cl::Hidden, - cl::init(false)); + cl::desc("sets a boolean flag for every edge"), + cl::Hidden); static cl::opt ClCMPTracing("sanitizer-coverage-trace-compares", cl::desc("Tracing of CMP and similar instructions"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClDIVTracing("sanitizer-coverage-trace-divs", cl::desc("Tracing of DIV instructions"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClLoadTracing("sanitizer-coverage-trace-loads", cl::desc("Tracing of load instructions"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClStoreTracing("sanitizer-coverage-trace-stores", cl::desc("Tracing of store instructions"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClGEPTracing("sanitizer-coverage-trace-geps", cl::desc("Tracing of GEP instructions"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClPruneBlocks("sanitizer-coverage-prune-blocks", @@ -147,12 +146,11 @@ static cl::opt static cl::opt ClStackDepth("sanitizer-coverage-stack-depth", cl::desc("max stack depth tracing"), - cl::Hidden, cl::init(false)); + cl::Hidden); static cl::opt ClCollectCF("sanitizer-coverage-control-flow", - cl::desc("collect control flow for each function"), cl::Hidden, - cl::init(false)); + cl::desc("collect control flow for each function"), cl::Hidden); namespace { @@ -213,8 +211,7 @@ public: ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options, const SpecialCaseList *Allowlist, const SpecialCaseList *Blocklist) - : Options(Options), Allowlist(Allowlist), - Blocklist(Blocklist) {} + : Options(Options), Allowlist(Allowlist), Blocklist(Blocklist) {} bool instrumentModule(Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); -- GitLab From 30257dd4ae47ceb77c55481ecead02db79db8a51 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 18:55:59 -0700 Subject: [PATCH 069/357] [NFC][SanCov] Move Module and analysis callbacks into ModuleSanitizerCoverage class Avoid passing them around. --- .../Instrumentation/SanitizerCoverage.cpp | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 2cd2cc04a3c0..4a687dcdeb52 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -208,18 +208,19 @@ public: using PostDomTreeCallback = function_ref; - ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options, + ModuleSanitizerCoverage(Module &M, DomTreeCallback DTCallback, + PostDomTreeCallback PDTCallback, + const SanitizerCoverageOptions &Options, const SpecialCaseList *Allowlist, const SpecialCaseList *Blocklist) - : Options(Options), Allowlist(Allowlist), Blocklist(Blocklist) {} + : M(M), DTCallback(DTCallback), PDTCallback(PDTCallback), + Options(Options), Allowlist(Allowlist), Blocklist(Blocklist) {} - bool instrumentModule(Module &M, DomTreeCallback DTCallback, - PostDomTreeCallback PDTCallback); + bool instrumentModule(); private: void createFunctionControlFlow(Function &F); - void instrumentFunction(Function &F, DomTreeCallback DTCallback, - PostDomTreeCallback PDTCallback); + void instrumentFunction(Function &F); void InjectCoverageForIndirectCalls(Function &F, ArrayRef IndirCalls); void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets); @@ -249,6 +250,11 @@ private: std::string getSectionName(const std::string &Section) const; std::string getSectionStart(const std::string &Section) const; std::string getSectionEnd(const std::string &Section) const; + + Module &M; + DomTreeCallback DTCallback; + PostDomTreeCallback PDTCallback; + FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC, SanCovTracePCGuard; std::array SanCovTraceCmpFunction; @@ -283,8 +289,6 @@ private: PreservedAnalyses SanitizerCoveragePass::run(Module &M, ModuleAnalysisManager &MAM) { - ModuleSanitizerCoverage ModuleSancov(OverrideFromCL(Options), Allowlist.get(), - Blocklist.get()); auto &FAM = MAM.getResult(M).getManager(); auto DTCallback = [&FAM](Function &F) -> const DominatorTree & { return FAM.getResult(F); @@ -292,7 +296,10 @@ PreservedAnalyses SanitizerCoveragePass::run(Module &M, auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree & { return FAM.getResult(F); }; - if (!ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) + ModuleSanitizerCoverage ModuleSancov(M, DTCallback, PDTCallback, + OverrideFromCL(Options), Allowlist.get(), + Blocklist.get()); + if (!ModuleSancov.instrumentModule()) return PreservedAnalyses::all(); PreservedAnalyses PA = PreservedAnalyses::none(); @@ -363,8 +370,7 @@ Function *ModuleSanitizerCoverage::CreateInitCallsForSections( return CtorFunc; } -bool ModuleSanitizerCoverage::instrumentModule( - Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { +bool ModuleSanitizerCoverage::instrumentModule() { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; if (Allowlist && @@ -477,7 +483,7 @@ bool ModuleSanitizerCoverage::instrumentModule( M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, PtrTy); for (auto &F : M) - instrumentFunction(F, DTCallback, PDTCallback); + instrumentFunction(F); Function *Ctor = nullptr; @@ -596,8 +602,7 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree &DT, return true; } -void ModuleSanitizerCoverage::instrumentFunction( - Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { +void ModuleSanitizerCoverage::instrumentFunction(Function &F) { if (F.empty()) return; if (F.getName().contains(".module_ctor")) -- GitLab From 0ccdd4c28fca72d1e1d518c6ed9715e92fb47edf Mon Sep 17 00:00:00 2001 From: Ding Fei Date: Sat, 20 Apr 2024 10:11:02 +0800 Subject: [PATCH 070/357] [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) Lambda without trailing auto could have return type declared inside the body too. Fixes #68775 --- clang/docs/ReleaseNotes.rst | 3 +++ clang/lib/AST/ASTImporter.cpp | 23 ++++++++++++++++++----- clang/unittests/AST/ASTImporterTest.cpp | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index aea8fda35bb2..c44f238e3384 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -559,6 +559,9 @@ Bug Fixes to AST Handling Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed an infinite recursion in ASTImporter, on return type declared inside + body of C++11 lambda without trailing return (#GH68775). + Miscellaneous Clang Crashes Fixed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 6aaa34c55ce3..f8180047f686 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -695,7 +695,7 @@ namespace clang { // Returns true if the given function has a placeholder return type and // that type is declared inside the body of the function. // E.g. auto f() { struct X{}; return X(); } - bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D); + bool hasReturnTypeDeclaredInside(FunctionDecl *D); }; template @@ -3647,15 +3647,28 @@ private: }; } // namespace -/// This function checks if the function has 'auto' return type that contains +/// This function checks if the given function has a return type that contains /// a reference (in any way) to a declaration inside the same function. -bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { +bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs(); assert(FromFPT && "Must be called on FunctionProtoType"); + auto IsCXX11LambdaWithouTrailingReturn = [&]() { + if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later + return false; + + if (FromFPT->hasTrailingReturn()) + return false; + + if (const auto *MD = dyn_cast(D)) + return cast(MD->getDeclContext())->isLambda(); + + return false; + }; + QualType RetT = FromFPT->getReturnType(); - if (isa(RetT.getTypePtr())) { + if (isa(RetT.getTypePtr()) || IsCXX11LambdaWithouTrailingReturn()) { FunctionDecl *Def = D->getDefinition(); IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D); return Visitor.CheckType(RetT); @@ -3811,7 +3824,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // E.g.: auto foo() { struct X{}; return X(); } // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified return type. - if (hasAutoReturnTypeDeclaredInside(D)) { + if (hasReturnTypeDeclaredInside(D)) { FromReturnTy = Importer.getFromContext().VoidTy; UsedDifferentProtoType = true; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index acc596fef87b..4ee64de697d3 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6721,6 +6721,23 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) { EXPECT_FALSE(FromL->isDependentLambda()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) { + Decl *From, *To; + std::tie(From, To) = getImportedDecl( + R"( + void foo() { + (void) []() { + struct X {}; + return X(); + }; + } + )", + Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only + auto *ToLambda = FirstDeclMatcher().match(To, lambdaExpr()); + EXPECT_TRUE(ToLambda); +} + TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) { Decl *FromTU = getTuDecl( R"( -- GitLab From 6fedc18c9c25568c5aba6c0a7aaf5d2406bc84eb Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 19 Apr 2024 19:15:43 -0700 Subject: [PATCH 071/357] [NFC][SanCov] Re-format long line --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 4a687dcdeb52..56d4907ae47a 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -631,8 +631,10 @@ void ModuleSanitizerCoverage::instrumentFunction(Function &F) { return; if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; - if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) - SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); + if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) { + SplitAllCriticalEdges( + F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); + } SmallVector IndirCalls; SmallVector BlocksToInstrument; SmallVector CmpTraceTargets; -- GitLab From f03cd2db91956456f1c5e2da86d3c50183eebd28 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Fri, 19 Apr 2024 19:57:39 -0700 Subject: [PATCH 072/357] [clang][Apple][cmake] Disable plugin support at LLVM level (#89483) Matches up with the clang setting --- clang/cmake/caches/Apple-stage2.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/cmake/caches/Apple-stage2.cmake b/clang/cmake/caches/Apple-stage2.cmake index ede256a2da6b..e919c5673967 100644 --- a/clang/cmake/caches/Apple-stage2.cmake +++ b/clang/cmake/caches/Apple-stage2.cmake @@ -16,6 +16,7 @@ set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") set(LLVM_ENABLE_MODULES ON CACHE BOOL "") set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "") set(LLVM_ENABLE_EXPORTED_SYMBOLS_IN_EXECUTABLES OFF CACHE BOOL "") +set(LLVM_PLUGIN_SUPPORT OFF CACHE BOOL "") set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") set(CLANG_SPAWN_CC1 ON CACHE BOOL "") set(BUG_REPORT_URL "http://developer.apple.com/bugreporter/" CACHE STRING "") -- GitLab From c455b462da70e800124ca4f453c466ea05db6033 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Fri, 19 Apr 2024 20:21:43 -0700 Subject: [PATCH 073/357] [clang-format] Fix a bug in annotating CastRParen before unary && (#89346) Also fix a bug in annotating TrailingAnnotation. Closes #61233. --- clang/lib/Format/TokenAnnotator.cpp | 5 ++++- clang/unittests/Format/TokenAnnotatorTest.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a679683077ac..cdfb4256e41d 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1543,6 +1543,7 @@ private: return false; if (Line.MustBeDeclaration && Contexts.size() == 1 && !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) && + !Line.startsWith(tok::l_paren) && !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) { if (const auto *Previous = Tok->Previous; !Previous || @@ -2726,8 +2727,10 @@ private: } } - if (Tok.Next->isOneOf(tok::question, tok::ampamp)) + if (Tok.Next->is(tok::question) || + (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(IsCpp))) { return false; + } // `foreach((A a, B b) in someList)` should not be seen as a cast. if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp()) diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 4f445c64ab30..34999b737639 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -599,6 +599,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) { ASSERT_EQ(Tokens.size(), 6u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_CastRParen); + Tokens = annotate("(uint32_t)&&label;"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::r_paren, TT_CastRParen); + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_UnaryOperator); + EXPECT_TOKEN(Tokens[4], tok::identifier, TT_Unknown); + Tokens = annotate("auto x = (Foo)p;"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_CastRParen); -- GitLab From 22bf7c5e01e869bbbb3b2da722e1a33e69e931d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Thu, 18 Apr 2024 10:29:08 +0200 Subject: [PATCH 074/357] [clang][Interp] Support __builtin_os_log_format_buffer_size --- clang/lib/AST/Interp/InterpBuiltin.cpp | 17 +++++++++++++++++ clang/test/AST/Interp/builtin-functions.cpp | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index f562f9e1cb19..565c85bc2e0c 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -9,6 +9,7 @@ #include "Boolean.h" #include "Interp.h" #include "PrimType.h" +#include "clang/AST/OSLog.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" @@ -1088,6 +1089,17 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, return false; } +static bool interp__builtin_os_log_format_buffer_size(InterpState &S, + CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + analyze_os_log::OSLogBufferLayout Layout; + analyze_os_log::computeOSLogBufferLayout(S.getCtx(), Call, Layout); + pushInteger(S, Layout.size().getQuantity(), Call->getType()); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { const InterpFrame *Frame = S.Current; @@ -1409,6 +1421,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_os_log_format_buffer_size: + if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call)) + return false; + break; + default: S.FFDiag(S.Current->getLocation(OpPC), diag::note_invalid_subexpr_in_const_expr) diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 1a29a664d7ce..0cbab1fcd91d 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -633,3 +633,9 @@ void test7(void) { X = CFSTR("foo", "bar"); // both-error {{too many arguments to function call}} #endif } + +/// The actual value on my machine is 22, but I have a feeling this will be different +/// on other targets, so just checking for != 0 here. Light testing is fine since +/// the actual implementation uses analyze_os_log::computeOSLogBufferLayout(), which +/// is tested elsewhere. +static_assert(__builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc") != 0, ""); -- GitLab From 225ae82fdbbff7d22fbbf9aead00e67e08416ecf Mon Sep 17 00:00:00 2001 From: SahilPatidar Date: Sat, 20 Apr 2024 14:15:14 +0530 Subject: [PATCH 075/357] [InstCombine] fold `cond ? x : -x == 0` into `x == 0` (#85673) Resolve #85250 Alive2: https://alive2.llvm.org/ce/z/7DMRCy --- .../InstCombine/InstCombineCompares.cpp | 8 + llvm/test/Transforms/InstCombine/fcmp.ll | 232 ++++++++++++++++++ 2 files changed, 240 insertions(+) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fdadf729fbd5..f0278f207549 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -8045,6 +8045,14 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { Constant *RHSC; if (match(Op0, m_Instruction(LHSI)) && match(Op1, m_Constant(RHSC))) { switch (LHSI->getOpcode()) { + case Instruction::Select: + // fcmp eq (cond ? x : -x), 0 --> fcmp eq x, 0 + if (FCmpInst::isEquality(Pred) && match(RHSC, m_AnyZeroFP()) && + (match(LHSI, + m_Select(m_Value(), m_Value(X), m_FNeg(m_Deferred(X)))) || + match(LHSI, m_Select(m_Value(), m_FNeg(m_Value(X)), m_Deferred(X))))) + return replaceOperand(I, 0, X); + break; case Instruction::PHI: if (Instruction *NV = foldOpIntoPhi(I, cast(LHSI))) return NV; diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll index 389264e2f707..4d907800219d 100644 --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -1486,3 +1486,235 @@ define i1 @fcmp_fadd_fast_zero(float %x, float %y) { %cmp = fcmp ugt float %add, %y ret i1 %cmp } + +define i1 @fcmp_ueq_sel_x_negx(float %x) { +; CHECK-LABEL: @fcmp_ueq_sel_x_negx( +; CHECK-NEXT: [[RES:%.*]] = fcmp ueq float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp ueq float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp ueq float %sel, 0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_une_sel_x_negx(float %x) { +; CHECK-LABEL: @fcmp_une_sel_x_negx( +; CHECK-NEXT: [[RES:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp une float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp une float %sel, 0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_oeq_sel_x_negx(float %x) { +; CHECK-LABEL: @fcmp_oeq_sel_x_negx( +; CHECK-NEXT: [[RES:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp oeq float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp oeq float %sel, 0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_one_sel_x_negx(float %x) { +; CHECK-LABEL: @fcmp_one_sel_x_negx( +; CHECK-NEXT: [[RES:%.*]] = fcmp one float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp one float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp one float %sel, 0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_ueq_sel_x_negx_nzero(float %x) { +; CHECK-LABEL: @fcmp_ueq_sel_x_negx_nzero( +; CHECK-NEXT: [[RES:%.*]] = fcmp ueq float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp ueq float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp ueq float %sel, -0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_une_sel_x_negx_nzero(float %x) { +; CHECK-LABEL: @fcmp_une_sel_x_negx_nzero( +; CHECK-NEXT: [[RES:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp une float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp une float %sel, -0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_oeq_sel_x_negx_nzero(float %x) { +; CHECK-LABEL: @fcmp_oeq_sel_x_negx_nzero( +; CHECK-NEXT: [[RES:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp oeq float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp oeq float %sel, -0.000000e+00 + ret i1 %res +} + +define i1 @fcmp_one_sel_x_negx_nzero(float %x) { +; CHECK-LABEL: @fcmp_one_sel_x_negx_nzero( +; CHECK-NEXT: [[RES:%.*]] = fcmp one float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; + %f = fcmp one float %x, 0.000000e+00 + %neg = fneg float %x + %sel = select i1 %f, float %x, float %neg + %res = fcmp one float %sel, -0.000000e+00 + ret i1 %res +} + +define <8 x i1> @fcmp_ueq_sel_x_negx_vec(<8 x float> %x) { +; CHECK-LABEL: @fcmp_ueq_sel_x_negx_vec( +; CHECK-NEXT: [[RES:%.*]] = fcmp ueq <8 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <8 x i1> [[RES]] +; + %f = fcmp ueq <8 x float> %x, zeroinitializer + %neg = fneg <8 x float> %x + %sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg + %res = fcmp ueq <8 x float> %sel, zeroinitializer + ret <8 x i1> %res +} + +define <8 x i1> @fcmp_une_sel_x_negx_vec(<8 x float> %x) { +; CHECK-LABEL: @fcmp_une_sel_x_negx_vec( +; CHECK-NEXT: [[RES:%.*]] = fcmp une <8 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <8 x i1> [[RES]] +; + %f = fcmp une <8 x float> %x, zeroinitializer + %neg = fneg <8 x float> %x + %sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg + %res = fcmp une <8 x float> %sel, zeroinitializer + ret <8 x i1> %res +} + +define <8 x i1> @fcmp_oeq_sel_x_negx_vec(<8 x float> %x) { +; CHECK-LABEL: @fcmp_oeq_sel_x_negx_vec( +; CHECK-NEXT: [[RES:%.*]] = fcmp oeq <8 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <8 x i1> [[RES]] +; + %f = fcmp oeq <8 x float> %x, zeroinitializer + %neg = fneg <8 x float> %x + %sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg + %res = fcmp oeq <8 x float> %sel, zeroinitializer + ret <8 x i1> %res +} + +define <8 x i1> @fcmp_one_sel_x_negx_vec(<8 x float> %x) { +; CHECK-LABEL: @fcmp_one_sel_x_negx_vec( +; CHECK-NEXT: [[RES:%.*]] = fcmp one <8 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <8 x i1> [[RES]] +; + %f = fcmp one <8 x float> %x, zeroinitializer + %neg = fneg <8 x float> %x + %sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg + %res = fcmp one <8 x float> %sel, zeroinitializer + ret <8 x i1> %res +} + +define <2 x i1> @fcmp_oeq_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_oeq_sel_x_negx_with_any_fpzero_ninf_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf oeq <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp ninf oeq <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_one_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_one_sel_x_negx_with_any_fpzero_ninf_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf one <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp ninf one <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_ueq_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_ueq_sel_x_negx_with_any_fpzero_ninf_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf ueq <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp ninf ueq <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_une_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_une_sel_x_negx_with_any_fpzero_ninf_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf une <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp ninf une <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_oeq_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_oeq_sel_x_negx_with_any_fpzero_nnan_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan oeq <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp nnan oeq <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_one_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_one_sel_x_negx_with_any_fpzero_nnan_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan one <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp nnan one <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_ueq_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_ueq_sel_x_negx_with_any_fpzero_nnan_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan ueq <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp nnan ueq <2 x float> %sel, + ret <2 x i1> %icmp +} + +define <2 x i1> @fcmp_une_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) { +; CHECK-LABEL: @fcmp_une_sel_x_negx_with_any_fpzero_nnan_vec( +; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan une <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[ICMP]] +; + %fneg = fneg <2 x float> %x + %sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg + %icmp = fcmp nnan une <2 x float> %sel, + ret <2 x i1> %icmp +} -- GitLab From 29312d39ff89b664138c497716dd11d4e1f2876b Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Sat, 20 Apr 2024 11:40:18 +0200 Subject: [PATCH 076/357] [libc++] Optimize char_traits a bit (#72799) This implements two kinds of optimizations. Specifically - `char_traits` uses `char` code paths; these are heavily optimized and the operations are equivalent - `char16_t` and `char32_t` `find` uses `std::find` to forward to `wmemchr` if they have the same size --- libcxx/include/__string/char_traits.h | 68 +++++++------------ .../include/__string/constexpr_c_functions.h | 23 +++++-- 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h index 47ed1057caaa..1fd22d518e1a 100644 --- a/libcxx/include/__string/char_traits.h +++ b/libcxx/include/__string/char_traits.h @@ -10,6 +10,7 @@ #define _LIBCPP___STRING_CHAR_TRAITS_H #include <__algorithm/fill_n.h> +#include <__algorithm/find.h> #include <__algorithm/find_end.h> #include <__algorithm/find_first_of.h> #include <__algorithm/min.h> @@ -17,6 +18,7 @@ #include <__compare/ordering.h> #include <__config> #include <__functional/hash.h> +#include <__functional/identity.h> #include <__iterator/iterator_traits.h> #include <__string/constexpr_c_functions.h> #include <__type_traits/is_constant_evaluated.h> @@ -272,10 +274,14 @@ struct _LIBCPP_TEMPLATE_VIS char_traits { return std::__constexpr_memcmp(__s1, __s2, __element_count(__n)); } - static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __s) _NOEXCEPT; + static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) _NOEXCEPT { + return std::__constexpr_strlen(__str); + } _LIBCPP_HIDE_FROM_ABI static constexpr const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; + find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { + return std::__constexpr_memchr(__s, __a, __n); + } static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { @@ -307,25 +313,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits { static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type eof() noexcept { return int_type(EOF); } }; -// TODO use '__builtin_strlen' if it ever supports char8_t ?? -inline constexpr size_t char_traits::length(const char_type* __s) _NOEXCEPT { - size_t __len = 0; - for (; !eq(*__s, char_type(0)); ++__s) - ++__len; - return __len; -} - -// TODO use '__builtin_char_memchr' if it ever supports char8_t ?? -inline constexpr const char8_t* -char_traits::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { - for (; __n; --__n) { - if (eq(*__s, __a)) - return __s; - ++__s; - } - return nullptr; -} - #endif // _LIBCPP_HAS_NO_CHAR8_T template <> @@ -353,9 +340,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits { _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { + __identity __proj; + const char_type* __match = std::__find_impl(__s, __s + __n, __a, __proj); + if (__match == __s + __n) + return nullptr; + return __match; + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { return std::__constexpr_memmove(__s1, __s2, __element_count(__n)); @@ -408,16 +401,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits::length(const return __len; } -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 const char16_t* -char_traits::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { - for (; __n; --__n) { - if (eq(*__s, __a)) - return __s; - ++__s; - } - return nullptr; -} - template <> struct _LIBCPP_TEMPLATE_VIS char_traits { using char_type = char32_t; @@ -443,8 +426,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits { _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; + find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { + __identity __proj; + const char_type* __match = std::__find_impl(__s, __s + __n, __a, __proj); + if (__match == __s + __n) + return nullptr; + return __match; + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { @@ -496,16 +486,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits::length(const return __len; } -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 const char32_t* -char_traits::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { - for (; __n; --__n) { - if (eq(*__s, __a)) - return __s; - ++__s; - } - return nullptr; -} - // helper fns for basic_string and string_view // __str_find diff --git a/libcxx/include/__string/constexpr_c_functions.h b/libcxx/include/__string/constexpr_c_functions.h index 198f0f5e6809..72c6ce69b60b 100644 --- a/libcxx/include/__string/constexpr_c_functions.h +++ b/libcxx/include/__string/constexpr_c_functions.h @@ -35,18 +35,33 @@ _LIBCPP_BEGIN_NAMESPACE_STD // of elements as opposed to a number of bytes. enum class __element_count : size_t {}; -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) { +template +inline const bool __is_char_type = false; + +template <> +inline const bool __is_char_type = true; + +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template <> +inline const bool __is_char_type = true; +#endif + +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const _Tp* __str) _NOEXCEPT { + static_assert(__is_char_type<_Tp>, "__constexpr_strlen only works with char and char8_t"); // GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 -#ifdef _LIBCPP_COMPILER_GCC if (__libcpp_is_constant_evaluated()) { +#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_COMPILER_CLANG_BASED) + if constexpr (is_same_v<_Tp, char>) + return __builtin_strlen(__str); +#endif size_t __i = 0; for (; __str[__i] != '\0'; ++__i) ; return __i; } -#endif - return __builtin_strlen(__str); + return __builtin_strlen(reinterpret_cast(__str)); } // Because of __libcpp_is_trivially_lexicographically_comparable we know that comparing the object representations is -- GitLab From 32623a3fc09a87867df495ab8c059706f24a126c Mon Sep 17 00:00:00 2001 From: Amila Senadheera Date: Sat, 20 Apr 2024 15:17:57 +0530 Subject: [PATCH 077/357] [clang] Marshallers.h - use move semantics for 'NodeKinds' and update possible callers to use it (#87273) Fixes: https://github.com/llvm/llvm-project/issues/87248 Signed-off-by: amila --- clang/lib/ASTMatchers/Dynamic/Marshallers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index c76ddf17b719..0e640cbada72 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -937,7 +937,7 @@ class MapAnyOfMatcherDescriptor : public MatcherDescriptor { public: MapAnyOfMatcherDescriptor(ASTNodeKind CladeNodeKind, std::vector NodeKinds) - : CladeNodeKind(CladeNodeKind), NodeKinds(NodeKinds) {} + : CladeNodeKind(CladeNodeKind), NodeKinds(std::move(NodeKinds)) {} VariantMatcher create(SourceRange NameRange, ArrayRef Args, Diagnostics *Error) const override { @@ -1026,7 +1026,7 @@ public: } return std::make_unique(CladeNodeKind, - NodeKinds); + std::move(NodeKinds)); } bool isVariadic() const override { return true; } -- GitLab From a4422a51941bfcffc870d1e2fff682e5387f89c2 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sat, 20 Apr 2024 12:09:13 +0200 Subject: [PATCH 078/357] [libc++][TZDB] Renames incomplete. (#89250) The new name uses experimental which better conveys what it means. --- libcxx/include/__chrono/convert_to_tm.h | 2 +- libcxx/include/__chrono/formatter.h | 14 +++++++------- libcxx/include/__chrono/leap_second.h | 4 ++-- libcxx/include/__chrono/local_info.h | 4 ++-- libcxx/include/__chrono/ostream.h | 4 ++-- libcxx/include/__chrono/sys_info.h | 4 ++-- libcxx/include/__chrono/time_zone.h | 4 ++-- libcxx/include/__chrono/time_zone_link.h | 4 ++-- libcxx/include/__chrono/tzdb.h | 4 ++-- libcxx/include/__chrono/tzdb_list.h | 4 ++-- libcxx/include/__config | 2 +- .../chrono.nodiscard_extensions.compile.pass.cpp | 2 +- .../chrono.nodiscard_extensions.verify.cpp | 2 +- .../fexperimental-library.compile.pass.cpp | 2 +- .../time.zone/time.zone.db/leap_seconds.pass.cpp | 2 +- .../time/time.zone/time.zone.db/links.pass.cpp | 2 +- .../time/time.zone/time.zone.db/rules.pass.cpp | 2 +- .../time.zone.db.list/erase_after.pass.cpp | 2 +- .../time.zone.db.remote/reload_tzdb.pass.cpp | 2 +- .../time.zone.db.tzdb/locate_zone.pass.cpp | 2 +- .../time/time.zone/time.zone.db/version.pass.cpp | 2 +- .../time/time.zone/time.zone.db/zones.pass.cpp | 2 +- .../time.zone.info.local/ostream.pass.cpp | 2 +- .../time.zone.info.sys/ostream.pass.cpp | 2 +- .../time.zone.members/get_info.sys_time.pass.cpp | 2 +- .../get_info.sys_time.rule_selection.pass.cpp | 2 +- libcxx/test/libcxx/transitive_includes.gen.py | 2 +- .../time/time.syn/formatter.local_info.pass.cpp | 2 +- .../std/time/time.syn/formatter.sys_info.pass.cpp | 2 +- .../time.zone/time.zone.db/leap_seconds.pass.cpp | 2 +- .../time.zone.db.access/current_zone.pass.cpp | 2 +- .../time.zone.db.access/get_tzdb.pass.cpp | 2 +- .../time.zone.db.access/get_tzdb_list.pass.cpp | 2 +- .../time.zone.db.access/locate_zone.pass.cpp | 2 +- .../time.zone.db.list/erase_after.compile.pass.cpp | 2 +- .../time.zone.db/time.zone.db.list/front.pass.cpp | 2 +- .../time.zone.db.list/iterators.pass.cpp | 2 +- .../time.zone.db.list/types.compile.pass.cpp | 2 +- .../time.zone.db.remote/reload_tzdb.pass.cpp | 2 +- .../time.zone.db.remote/remote_version.pass.cpp | 2 +- .../time.zone.db.tzdb/current_zone.pass.cpp | 2 +- .../time.zone.db.tzdb/locate_zone.pass.cpp | 2 +- .../time.zone.db.tzdb/tzdb.members.pass.cpp | 2 +- .../local_info.members.pass.cpp | 2 +- .../time.zone.info.local/ostream.pass.cpp | 2 +- .../time.zone.info.sys/ostream.pass.cpp | 2 +- .../time.zone.info.sys/sys_info.members.pass.cpp | 2 +- .../time.zone/time.zone.leap/assign.copy.pass.cpp | 2 +- .../time.zone/time.zone.leap/cons.copy.pass.cpp | 2 +- .../time.zone/time.zone.leap/members/date.pass.cpp | 2 +- .../time.zone.leap/members/value.pass.cpp | 2 +- .../time.zone.leap/nonmembers/comparison.pass.cpp | 2 +- .../time.zone.link.members/name.pass.cpp | 2 +- .../time.zone.link.members/target.pass.cpp | 2 +- .../time.zone.link.nonmembers/comparison.pass.cpp | 2 +- .../time.zone.link/types.compile.pass.cpp | 2 +- .../time.zone.members/get_info.sys_time.pass.cpp | 2 +- .../time.zone.members/name.pass.cpp | 2 +- .../time.zone.members/sys_info.zdump.pass.cpp | 2 +- .../time.zone.nonmembers/comparison.pass.cpp | 2 +- .../time.zone.timezone/types.compile.pass.cpp | 2 +- .../concept.formattable.compile.pass.cpp | 4 ++-- libcxx/test/support/test_macros.h | 4 ++-- libcxx/utils/libcxx/test/params.py | 2 +- 64 files changed, 80 insertions(+), 80 deletions(-) diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index f7256db3bea6..881a4970822d 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -173,7 +173,7 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { if (__value.hours().count() > std::numeric_limits::max()) std::__throw_format_error("Formatting hh_mm_ss, encountered an hour overflow"); __result.tm_hour = __value.hours().count(); -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) } else if constexpr (same_as<_ChronoT, chrono::sys_info>) { // Has no time information. } else if constexpr (same_as<_ChronoT, chrono::local_info>) { diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 6a14c344fa11..226fccbee6d1 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -205,7 +205,7 @@ struct _LIBCPP_HIDE_FROM_ABI __time_zone { template _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const _Tp& __value) { -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) if constexpr (same_as<_Tp, chrono::sys_info>) return {__value.abbrev, __value.offset}; else @@ -417,7 +417,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -463,7 +463,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -509,7 +509,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { return __value.ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -555,7 +555,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { return __value.month().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; else if constexpr (same_as<_Tp, chrono::local_info>) @@ -891,7 +891,7 @@ public: } }; -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) template <__fmt_char_type _CharT> struct formatter : public __formatter_chrono<_CharT> { public: @@ -913,7 +913,7 @@ public: return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags{}); } }; -# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__chrono/leap_second.h b/libcxx/include/__chrono/leap_second.h index 557abc15ff18..2bbf06364673 100644 --- a/libcxx/include/__chrono/leap_second.h +++ b/libcxx/include/__chrono/leap_second.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/system_clock.h> @@ -121,6 +121,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const leap_second& __x, const s _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_LEAP_SECOND_H diff --git a/libcxx/include/__chrono/local_info.h b/libcxx/include/__chrono/local_info.h index b1a03ad7df2a..cfe1448904d3 100644 --- a/libcxx/include/__chrono/local_info.h +++ b/libcxx/include/__chrono/local_info.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/sys_info.h> # include <__config> @@ -45,6 +45,6 @@ struct local_info { _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_LOCAL_INFO_H diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h index cb17dbea58be..ecf07a320c8b 100644 --- a/libcxx/include/__chrono/ostream.h +++ b/libcxx/include/__chrono/ostream.h @@ -264,7 +264,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const hh_mm_ss<_Duration> __hms return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%T}"), __hms); } -# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) template _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& @@ -302,7 +302,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __info) { _LIBCPP_STATICALLY_WIDEN(_CharT, "{}: {{{}, {}}}"), __result(), __info.first, __info.second); } -# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +# endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) } // namespace chrono diff --git a/libcxx/include/__chrono/sys_info.h b/libcxx/include/__chrono/sys_info.h index 461d5322d413..11536cbde3a3 100644 --- a/libcxx/include/__chrono/sys_info.h +++ b/libcxx/include/__chrono/sys_info.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/system_clock.h> @@ -46,6 +46,6 @@ struct sys_info { _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_SYS_INFO_H diff --git a/libcxx/include/__chrono/time_zone.h b/libcxx/include/__chrono/time_zone.h index 8e30034b799a..799602c1cdba 100644 --- a/libcxx/include/__chrono/time_zone.h +++ b/libcxx/include/__chrono/time_zone.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/sys_info.h> @@ -92,6 +92,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TIME_ZONE_H diff --git a/libcxx/include/__chrono/time_zone_link.h b/libcxx/include/__chrono/time_zone_link.h index c76ddeff9f96..f44137829a81 100644 --- a/libcxx/include/__chrono/time_zone_link.h +++ b/libcxx/include/__chrono/time_zone_link.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__compare/strong_order.h> # include <__config> @@ -74,6 +74,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TIME_ZONE_LINK_H diff --git a/libcxx/include/__chrono/tzdb.h b/libcxx/include/__chrono/tzdb.h index e0bfedf0d782..12fe6ccb63f9 100644 --- a/libcxx/include/__chrono/tzdb.h +++ b/libcxx/include/__chrono/tzdb.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__algorithm/ranges_lower_bound.h> # include <__chrono/leap_second.h> @@ -89,6 +89,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TZDB_H diff --git a/libcxx/include/__chrono/tzdb_list.h b/libcxx/include/__chrono/tzdb_list.h index 693899d37211..ae27067dbf02 100644 --- a/libcxx/include/__chrono/tzdb_list.h +++ b/libcxx/include/__chrono/tzdb_list.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__availability> # include <__chrono/time_zone.h> @@ -105,6 +105,6 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TZDB_LIST_H diff --git a/libcxx/include/__config b/libcxx/include/__config index 4ccef2ca0d73..4f5c1476626d 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -421,7 +421,7 @@ _LIBCPP_HARDENING_MODE_DEBUG # if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) # define _LIBCPP_HAS_NO_INCOMPLETE_PSTL # define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN -# define _LIBCPP_HAS_NO_INCOMPLETE_TZDB +# define _LIBCPP_HAS_NO_EXPERIMENTAL_TZDB # define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM # endif diff --git a/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.compile.pass.cpp b/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.compile.pass.cpp index cbdb2ab1758e..f0ea6a8f2c77 100644 --- a/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.compile.pass.cpp +++ b/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.compile.pass.cpp @@ -12,7 +12,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.verify.cpp b/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.verify.cpp index e88c176af4a8..a5ce5d165813 100644 --- a/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.verify.cpp @@ -11,7 +11,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp index 7c98ff1c1d56..3d50d2347d6b 100644 --- a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp +++ b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp @@ -24,7 +24,7 @@ # error "-fexperimental-library should enable the stop_token" #endif -#ifdef _LIBCPP_HAS_NO_INCOMPLETE_TZDB +#ifdef _LIBCPP_HAS_NO_EXPERIMENTAL_TZDB # error "-fexperimental-library should enable the chrono TZDB" #endif diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp index 282bddcf9adb..25a0f00003da 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/leap_seconds.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/links.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/links.pass.cpp index 92d761d46bcc..9bace25629f7 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/links.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/links.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp index fcfc34625fbe..73f4dbd59af9 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.list/erase_after.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.list/erase_after.pass.cpp index 9b6e2776fe13..92842800f6bb 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.list/erase_after.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.list/erase_after.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp index 94c403dbe396..5da4c7eea11b 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp index 971f7f04c49a..3ee213358f35 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp index 0f0095a71b99..b4f32a1b6fd7 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/version.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp index e97b36fca2bb..6d436d61357b 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp index d18076a642ec..b3fbaaf30aae 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp @@ -12,7 +12,7 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp index faa7d855c8de..6b41c7bdf234 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp @@ -12,7 +12,7 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp index 194f58215b92..7f08c64d5e0e 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.rule_selection.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.rule_selection.pass.cpp index accd5bcdc89e..33c5d0499bca 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.rule_selection.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.rule_selection.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/libcxx/transitive_includes.gen.py b/libcxx/test/libcxx/transitive_includes.gen.py index 28f223c422a9..e4e1d3f232c1 100644 --- a/libcxx/test/libcxx/transitive_includes.gen.py +++ b/libcxx/test/libcxx/transitive_includes.gen.py @@ -64,7 +64,7 @@ else: {lit_header_restrictions.get(header, '')} // TODO: Fix this test to make it work with localization or wide characters disabled -// UNSUPPORTED{BLOCKLIT}: no-localization, no-wide-characters, no-threads, no-filesystem, libcpp-has-no-incomplete-tzdb, no-tzdb +// UNSUPPORTED{BLOCKLIT}: no-localization, no-wide-characters, no-threads, no-filesystem, libcpp-has-no-experimental-tzdb, no-tzdb // When built with modules, this test doesn't work because --trace-includes doesn't // report the stack of includes correctly. diff --git a/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp b/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp index ef36416c3fb2..019a1fc47327 100644 --- a/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp @@ -12,7 +12,7 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // REQUIRES: locale.fr_FR.UTF-8 diff --git a/libcxx/test/std/time/time.syn/formatter.sys_info.pass.cpp b/libcxx/test/std/time/time.syn/formatter.sys_info.pass.cpp index 0a41424cfdcb..d57977413b69 100644 --- a/libcxx/test/std/time/time.syn/formatter.sys_info.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.sys_info.pass.cpp @@ -11,7 +11,7 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // REQUIRES: locale.fr_FR.UTF-8 // REQUIRES: locale.ja_JP.UTF-8 diff --git a/libcxx/test/std/time/time.zone/time.zone.db/leap_seconds.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/leap_seconds.pass.cpp index 4fcdf6fab997..f873ad316781 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/leap_seconds.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/leap_seconds.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/current_zone.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/current_zone.pass.cpp index d85c8ba52622..2c43e121613c 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/current_zone.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/current_zone.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp index 470a722d0b69..6780bbff3682 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp index a5579a3820b6..4eadbf495f81 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/locate_zone.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/locate_zone.pass.cpp index c3142a86bf9d..4d600fcdf40e 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/locate_zone.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/locate_zone.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/erase_after.compile.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/erase_after.compile.pass.cpp index b6844786b489..db276147773b 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/erase_after.compile.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/erase_after.compile.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp index 12c5310772f6..01167365d950 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp index b00b8b44188d..6759a0155450 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/types.compile.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/types.compile.pass.cpp index 2c2e3a8274a4..774037fa263c 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/types.compile.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/types.compile.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp index af38772ee3cb..5e1dd478d34b 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp index 36b68cefc8d3..554f259eb5c2 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/current_zone.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/current_zone.pass.cpp index 7b4218cc8421..e6497e26323c 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/current_zone.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/current_zone.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp index 12987f6c89d8..f929dafcc968 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/locate_zone.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/tzdb.members.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/tzdb.members.pass.cpp index af95274e33a8..5d31cbfb8b22 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/tzdb.members.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.tzdb/tzdb.members.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info.members.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info.members.pass.cpp index 4e2a757a0a97..f246d5954d63 100644 --- a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info.members.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info.members.pass.cpp @@ -8,7 +8,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // diff --git a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp index d9bf066b0687..e144add46427 100644 --- a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp @@ -12,7 +12,7 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // diff --git a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp index 82c4844b423c..18fab6ee56e5 100644 --- a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/ostream.pass.cpp @@ -12,7 +12,7 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // diff --git a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/sys_info.members.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/sys_info.members.pass.cpp index 2510792c2280..bfbe9b90ada6 100644 --- a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/sys_info.members.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.sys/sys_info.members.pass.cpp @@ -8,7 +8,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // diff --git a/libcxx/test/std/time/time.zone/time.zone.leap/assign.copy.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.leap/assign.copy.pass.cpp index 6918ed6be5c1..7ea692dde8a2 100644 --- a/libcxx/test/std/time/time.zone/time.zone.leap/assign.copy.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.leap/assign.copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.leap/cons.copy.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.leap/cons.copy.pass.cpp index 3dad08968d12..79ed08608115 100644 --- a/libcxx/test/std/time/time.zone/time.zone.leap/cons.copy.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.leap/cons.copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.leap/members/date.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.leap/members/date.pass.cpp index 6f9fe1c47d35..bd148689f96f 100644 --- a/libcxx/test/std/time/time.zone/time.zone.leap/members/date.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.leap/members/date.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.leap/members/value.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.leap/members/value.pass.cpp index 652e51ef0bf1..c6181ee7df9f 100644 --- a/libcxx/test/std/time/time.zone/time.zone.leap/members/value.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.leap/members/value.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.leap/nonmembers/comparison.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.leap/nonmembers/comparison.pass.cpp index bf6855ea63df..448cd88d146f 100644 --- a/libcxx/test/std/time/time.zone/time.zone.leap/nonmembers/comparison.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.leap/nonmembers/comparison.pass.cpp @@ -12,7 +12,7 @@ // TODO TZDB test whether this can be enabled with gcc 14. // UNSUPPORTED: gcc-13 -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp index c2412bac461b..593675cfba45 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp index 2f8b5b9421d6..aa97fdadcebc 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp index 944818c1ad0c..22c270f24d18 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.link/types.compile.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/types.compile.pass.cpp index 2e4f178c7c05..268e78c9dcad 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/types.compile.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/types.compile.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp index d27cf0bd8906..25d2ff11d093 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/get_info.sys_time.pass.cpp @@ -12,7 +12,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23, c++26 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp index d1ff2fe68310..b9f473829279 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/sys_info.zdump.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/sys_info.zdump.pass.cpp index 05328e2256c7..50b7bdb568d4 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/sys_info.zdump.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/sys_info.zdump.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb, has-no-zdump -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // TODO TZDB Investigate diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp index 7c680707bc51..e362b183fca0 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/types.compile.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/types.compile.pass.cpp index 915d5596bf22..926ecef36701 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/types.compile.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/types.compile.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: no-filesystem, no-localization, no-tzdb -// XFAIL: libcpp-has-no-incomplete-tzdb +// XFAIL: libcpp-has-no-experimental-tzdb // XFAIL: availability-tzdb-missing // diff --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp index fd3416f694ba..94a1ea576bda 100644 --- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp @@ -176,12 +176,12 @@ void test_P1361() { assert_is_formattable, CharT>(); -# if !defined(TEST_HAS_NO_INCOMPLETE_TZDB) +# if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) assert_is_formattable(); assert_is_formattable(); //assert_is_formattable(); -# endif // !defined(TEST_HAS_NO_INCOMPLETE_TZDB) +# endif // !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) #endif // TEST_HAS_NO_LOCALIZATION } diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h index fe9207d7e596..68dd591cb575 100644 --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -417,8 +417,8 @@ inline Tp const& DoNotOptimize(Tp const& value) { # define TEST_HAS_NO_RANDOM_DEVICE #endif -#if defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) -# define TEST_HAS_NO_INCOMPLETE_TZDB +#if defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) +# define TEST_HAS_NO_EXPERIMENTAL_TZDB #endif #if defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index 5e42562ed5db..c2d294e49f48 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -331,7 +331,7 @@ DEFAULT_PARAMETERS = [ else [ AddFeature("libcpp-has-no-incomplete-pstl"), AddFeature("libcpp-has-no-experimental-stop_token"), - AddFeature("libcpp-has-no-incomplete-tzdb"), + AddFeature("libcpp-has-no-experimental-tzdb"), AddFeature("libcpp-has-no-experimental-syncstream"), ], ), -- GitLab From 55ed4e314fb6f2c3e66113931088c36e6bcfca74 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 20 Apr 2024 13:11:24 +0300 Subject: [PATCH 079/357] [Clang][Sema] Remove invalid ctor (NFC) (#82161) `TemplateArgumentLocInventIterator` default constructor should not exists https://github.com/llvm/llvm-project/blob/3496927edcd0685807351ba88a7e2cfb006e1c0d/clang/lib/Sema/TreeTransform.h#L4742 because it doesn't and couldn't initialize `Self` member that is reference: https://github.com/llvm/llvm-project/blob/3496927edcd0685807351ba88a7e2cfb006e1c0d/clang/lib/Sema/TreeTransform.h#L4721-L4723 Instantiation of this constructor is always a compile-time error. Please note, that I didn't run any tests, because cannot imagine situation where this constructor can be properly used. There are no new tests for this fix for the same reason. --- clang/lib/Sema/TreeTransform.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index ade33ec65038..180574f1cab8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4759,8 +4759,6 @@ public: const TemplateArgumentLoc *operator->() const { return &Arg; } }; - TemplateArgumentLocInventIterator() { } - explicit TemplateArgumentLocInventIterator(TreeTransform &Self, InputIterator Iter) : Self(Self), Iter(Iter) { } -- GitLab From 95e668f8c8a746bc10805d4a77d192cef3dc286e Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sat, 20 Apr 2024 12:19:23 +0200 Subject: [PATCH 080/357] [libc++] Removes a Clang 16 Windows workaround. (#88560) --- libcxx/include/sstream | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/libcxx/include/sstream b/libcxx/include/sstream index 5873deb8318e..003c802b2647 100644 --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -330,14 +330,6 @@ typedef basic_stringstream wstringstream; _LIBCPP_PUSH_MACROS #include <__undef_macros> -// TODO(LLVM-19): Remove this once we drop support for Clang 16, -// which had this bug: https://github.com/llvm/llvm-project/issues/40363 -#ifdef _WIN32 -# define _LIBCPP_HIDE_FROM_ABI_SSTREAM _LIBCPP_ALWAYS_INLINE -#else -# define _LIBCPP_HIDE_FROM_ABI_SSTREAM _LIBCPP_HIDE_FROM_ABI -#endif - _LIBCPP_BEGIN_NAMESPACE_STD // Class template basic_stringbuf [stringbuf] @@ -460,9 +452,9 @@ public: #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) string_type str() const; #else - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() const& { return str(__str_.get_allocator()); } + _LIBCPP_HIDE_FROM_ABI string_type str() const& { return str(__str_.get_allocator()); } - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() && { + _LIBCPP_HIDE_FROM_ABI string_type str() && { const basic_string_view<_CharT, _Traits> __view = view(); typename string_type::size_type __pos = __view.empty() ? 0 : __view.data() - __str_.data(); // In C++23, this is just string_type(std::move(__str_), __pos, __view.size(), __str_.get_allocator()); @@ -948,9 +940,9 @@ public: #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } #else - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() const& { return __sb_.str(); } + _LIBCPP_HIDE_FROM_ABI string_type str() const& { return __sb_.str(); } - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() && { return std::move(__sb_).str(); } + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } #endif #if _LIBCPP_STD_VER >= 20 @@ -1085,9 +1077,9 @@ public: #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } #else - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() const& { return __sb_.str(); } + _LIBCPP_HIDE_FROM_ABI string_type str() const& { return __sb_.str(); } - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() && { return std::move(__sb_).str(); } + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } #endif #if _LIBCPP_STD_VER >= 20 @@ -1225,9 +1217,9 @@ public: #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } #else - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() const& { return __sb_.str(); } + _LIBCPP_HIDE_FROM_ABI string_type str() const& { return __sb_.str(); } - _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() && { return std::move(__sb_).str(); } + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } #endif #if _LIBCPP_STD_VER >= 20 -- GitLab From 31480b0cc8fe2bb1e080ffd38e38780ba7e8dec6 Mon Sep 17 00:00:00 2001 From: Karl-Johan Karlsson Date: Sat, 20 Apr 2024 12:26:58 +0200 Subject: [PATCH 081/357] [test] Avoid writing to a potentially write-protected dir (#89242) These tests just don't check the output written to the current directory. The current directory may be write protected e.g. in a sandboxed environment. The Testcases that use -emit-llvm and -verify only care about stdout/stderr and are in this patch changed to use -emit-llvm-only to avoid writing to an output file. The verify-inlineasmbr.mir testcase that also only care about stdout/stderr is in this patch changed to throw away the output file and just write to /dev/null. --- clang/test/CodeGen/PowerPC/builtins-ppc-htm.c | 2 +- .../PowerPC/builtins-ppc-vec-ins-error.c | 12 +++++----- .../RISCV/riscv-func-attr-target-err.c | 2 +- clang/test/Sema/ppc-attr-target-inline.c | 2 +- clang/test/SemaHLSL/BuiltIns/any-errors.hlsl | 2 +- .../test/SemaHLSL/BuiltIns/clamp-errors.hlsl | 2 +- clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl | 2 +- clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl | 4 ++-- clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl | 2 +- .../BuiltIns/half-float-only-errors.hlsl | 24 +++++++++---------- .../test/SemaHLSL/BuiltIns/isinf-errors.hlsl | 2 +- clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl | 2 +- clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl | 2 +- clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl | 2 +- clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl | 2 +- .../SemaHLSL/BuiltIns/reversebits-errors.hlsl | 2 +- .../test/SemaHLSL/BuiltIns/round-errors.hlsl | 2 +- .../test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl | 2 +- .../MachineVerifier/verify-inlineasmbr.mir | 2 +- 19 files changed, 36 insertions(+), 36 deletions(-) diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c b/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c index 51585f27e0bc..eeb13b097819 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-htm.c @@ -1,6 +1,6 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -target-feature +altivec -target-feature +htm -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s -// RUN: not %clang_cc1 -target-feature +altivec -target-feature -htm -triple powerpc64-unknown-unknown -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=ERROR +// RUN: not %clang_cc1 -target-feature +altivec -target-feature -htm -triple powerpc64-unknown-unknown -emit-llvm-only %s 2>&1 | FileCheck %s --check-prefix=ERROR void test1(long int *r, int code, long int *a, long int *b) { // CHECK-LABEL: define{{.*}} void @test1 diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c b/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c index f5149bf4ce8f..485ef84df086 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c @@ -1,17 +1,17 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_SI +// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_SI // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_F +// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_F // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_SLL +// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_SLL // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_D +// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_D // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_UNALIGNED_UI +// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_UNALIGNED_UI // RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \ -// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify +// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify #include 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 b303d71304bf..66d15a7d1bc0 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c @@ -1,6 +1,6 @@ // REQUIRES: riscv-registered-target // RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \ -// RUN: -emit-llvm %s 2>&1 | FileCheck %s +// RUN: -emit-llvm-only %s 2>&1 | FileCheck %s #include diff --git a/clang/test/Sema/ppc-attr-target-inline.c b/clang/test/Sema/ppc-attr-target-inline.c index 07ed00682265..ad198b842bb0 100644 --- a/clang/test/Sema/ppc-attr-target-inline.c +++ b/clang/test/Sema/ppc-attr-target-inline.c @@ -1,5 +1,5 @@ // REQUIRES: powerpc-registered-target -// RUN: %clang_cc1 -triple powerpc64le -target-feature +htm -fsyntax-only -emit-llvm %s -verify +// RUN: %clang_cc1 -triple powerpc64le -target-feature +htm -fsyntax-only -emit-llvm-only %s -verify __attribute__((always_inline)) int test1(int *x) { diff --git a/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl index 862b94652073..7bb5308c5d5b 100644 --- a/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected bool test_too_few_arg() { return __builtin_hlsl_elementwise_any(); diff --git a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl index 4c0e5315ce53..f669098ef515 100644 --- a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float2 test_no_second_arg(float2 p0) { return __builtin_hlsl_elementwise_clamp(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl index ba7ffc20484a..095f3c12ba87 100644 --- a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_no_second_arg(float2 p0) { return __builtin_hlsl_dot(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl index e2e79abb74a3..321fc915ec01 100644 --- a/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp2 float test_too_few_arg() { return TEST_FUNC(); // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} diff --git a/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl index f82b5942fd46..f3cfbcf29d69 100644 --- a/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_hlsl_elementwise_frac(); diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl index 98c02c38675f..ef0928f8fef0 100644 --- a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl @@ -1,15 +1,15 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_ceil -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_cos -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp2 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_floor -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log2 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_ceil +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_cos +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_floor +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc double2 test_double_builtin(double2 p0) { return TEST_FUNC(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl index 7ddfd5663827..e2f03812705f 100644 --- a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected bool test_too_few_arg() { return __builtin_hlsl_elementwise_isinf(); diff --git a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl index 83751f68357e..d23357239b7e 100644 --- a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float2 test_no_second_arg(float2 p0) { return __builtin_hlsl_lerp(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl index 97ce931bf1b5..636910b7ac8a 100644 --- a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float2 test_no_second_arg(float2 p0) { return __builtin_hlsl_mad(p0); diff --git a/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl index 949028aacf24..5a2c9a3ef62f 100644 --- a/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify double2 test_double_builtin(double2 p0, double2 p1) { return __builtin_elementwise_pow(p0,p1); diff --git a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl index fa6fd813f19e..6bc5b9bed304 100644 --- a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_hlsl_elementwise_rcp(); diff --git a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl index 6e66db6d1cca..49cd895d98c5 100644 --- a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify double2 test_int_builtin(double2 p0) { diff --git a/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl index fed4573063ac..bede89015298 100644 --- a/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_elementwise_round(); diff --git a/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl index c027a698c5e5..e9a295172c7f 100644 --- a/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected float test_too_few_arg() { return __builtin_hlsl_elementwise_rsqrt(); diff --git a/llvm/test/MachineVerifier/verify-inlineasmbr.mir b/llvm/test/MachineVerifier/verify-inlineasmbr.mir index fd3cbc5f8b23..fe54379c1bc7 100644 --- a/llvm/test/MachineVerifier/verify-inlineasmbr.mir +++ b/llvm/test/MachineVerifier/verify-inlineasmbr.mir @@ -1,4 +1,4 @@ -# RUN: not --crash llc -run-pass=none -verify-machineinstrs %s 2>&1 \ +# RUN: not --crash llc -run-pass=none -verify-machineinstrs %s -o /dev/null 2>&1 \ # RUN: | FileCheck %s # REQUIRES: powerpc-registered-target -- GitLab From 60baaf153d05a7828b304050aba461ebb66232c6 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Sat, 20 Apr 2024 19:52:12 +0800 Subject: [PATCH 082/357] [mlir] fix typo in mem2reg [NFC] --- mlir/lib/Transforms/Mem2Reg.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mlir/lib/Transforms/Mem2Reg.cpp b/mlir/lib/Transforms/Mem2Reg.cpp index 1e620e46af84..0c1ce70f0708 100644 --- a/mlir/lib/Transforms/Mem2Reg.cpp +++ b/mlir/lib/Transforms/Mem2Reg.cpp @@ -46,7 +46,7 @@ using namespace mlir; /// Control flow can create situations where a load could be replaced by /// multiple possible stores depending on the control flow path taken. As a /// result, this pass must introduce new block arguments in some blocks to -/// accomodate for the multiple possible definitions. Each predecessor will +/// accommodate for the multiple possible definitions. Each predecessor will /// populate the block argument with the definition reached at its end. With /// this, the value stored can be well defined at block boundaries, allowing /// the propagation of replacement through blocks. @@ -109,7 +109,7 @@ struct MemorySlotPromotionInfo { /// This is a DAG structure because if an operation must eliminate some of /// its uses, it is because the defining ops of the blocking uses requested /// it. The defining ops therefore must also have blocking uses or be the - /// starting point of the bloccking uses. + /// starting point of the blocking uses. BlockingUsesMap userToBlockingUses; }; @@ -414,7 +414,7 @@ MemorySlotPromotionAnalyzer::computeInfo() { // Then, compute blocks in which two or more definitions of the allocated // variable may conflict. These blocks will need a new block argument to - // accomodate this. + // accommodate this. computeMergePoints(info.mergePoints); // The slot can be promoted if the block arguments to be created can -- GitLab From d8503a38b974930599417a747cec3615330c367e Mon Sep 17 00:00:00 2001 From: Haohai Wen Date: Sat, 20 Apr 2024 22:07:41 +0800 Subject: [PATCH 083/357] [InstCombine] Update BranchProbabilityAnalysis cache result (#86470) InstCombine may invert branch condition and profile metadata. In such case, BranchProbabilityAnalysis should also be updated. --- .../Transforms/InstCombine/InstCombiner.h | 7 +++-- .../InstCombine/InstCombineInternal.h | 6 ++-- .../InstCombine/InstructionCombining.cpp | 29 +++++++++++++++---- .../test/Transforms/InstCombine/update-bpi.ll | 4 +-- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h index 93090431cbb6..ea1f4fc3b85d 100644 --- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h +++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h @@ -76,6 +76,7 @@ protected: SimplifyQuery SQ; OptimizationRemarkEmitter &ORE; BlockFrequencyInfo *BFI; + BranchProbabilityInfo *BPI; ProfileSummaryInfo *PSI; DomConditionCache DC; @@ -96,13 +97,13 @@ public: bool MinimizeSize, AAResults *AA, AssumptionCache &AC, TargetLibraryInfo &TLI, TargetTransformInfo &TTI, DominatorTree &DT, OptimizationRemarkEmitter &ORE, - BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, - const DataLayout &DL, LoopInfo *LI) + BlockFrequencyInfo *BFI, BranchProbabilityInfo *BPI, + ProfileSummaryInfo *PSI, const DataLayout &DL, LoopInfo *LI) : TTI(TTI), Builder(Builder), Worklist(Worklist), MinimizeSize(MinimizeSize), AA(AA), AC(AC), TLI(TLI), DT(DT), DL(DL), SQ(DL, &TLI, &DT, &AC, nullptr, /*UseInstrInfo*/ true, /*CanUseUndef*/ true, &DC), - ORE(ORE), BFI(BFI), PSI(PSI), LI(LI) {} + ORE(ORE), BFI(BFI), BPI(BPI), PSI(PSI), LI(LI) {} virtual ~InstCombiner() = default; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index f4d559036b31..4479afbd09af 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -67,10 +67,10 @@ public: bool MinimizeSize, AAResults *AA, AssumptionCache &AC, TargetLibraryInfo &TLI, TargetTransformInfo &TTI, DominatorTree &DT, OptimizationRemarkEmitter &ORE, - BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, - const DataLayout &DL, LoopInfo *LI) + BlockFrequencyInfo *BFI, BranchProbabilityInfo *BPI, + ProfileSummaryInfo *PSI, const DataLayout &DL, LoopInfo *LI) : InstCombiner(Worklist, Builder, MinimizeSize, AA, AC, TLI, TTI, DT, ORE, - BFI, PSI, DL, LI) {} + BFI, BPI, PSI, DL, LI) {} virtual ~InstCombinerImpl() = default; diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index ee9b1afbb86a..3ac5c2559ddf 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1347,9 +1347,13 @@ void InstCombinerImpl::freelyInvertAllUsersOf(Value *I, Value *IgnoredUser) { SI->swapProfMetadata(); break; } - case Instruction::Br: - cast(U)->swapSuccessors(); // swaps prof metadata too + case Instruction::Br: { + BranchInst *BI = cast(U); + BI->swapSuccessors(); // swaps prof metadata too + if (BPI) + BPI->swapSuccEdgesProbabilities(BI->getParent()); break; + } case Instruction::Xor: replaceInstUsesWith(cast(*U), I); // Add to worklist for DCE. @@ -3525,6 +3529,8 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) { if (match(Cond, m_Not(m_Value(X))) && !isa(X)) { // Swap Destinations and condition... BI.swapSuccessors(); + if (BPI) + BPI->swapSuccEdgesProbabilities(BI.getParent()); return replaceOperand(BI, 0, X); } @@ -3538,6 +3544,8 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) { Value *NotX = Builder.CreateNot(X, "not." + X->getName()); Value *Or = Builder.CreateLogicalOr(NotX, Y); BI.swapSuccessors(); + if (BPI) + BPI->swapSuccEdgesProbabilities(BI.getParent()); return replaceOperand(BI, 0, Or); } @@ -3554,6 +3562,8 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) { auto *Cmp = cast(Cond); Cmp->setPredicate(CmpInst::getInversePredicate(Pred)); BI.swapSuccessors(); + if (BPI) + BPI->swapSuccEdgesProbabilities(BI.getParent()); Worklist.push(Cmp); return &BI; } @@ -5248,7 +5258,8 @@ static bool combineInstructionsOverFunction( Function &F, InstructionWorklist &Worklist, AliasAnalysis *AA, AssumptionCache &AC, TargetLibraryInfo &TLI, TargetTransformInfo &TTI, DominatorTree &DT, OptimizationRemarkEmitter &ORE, BlockFrequencyInfo *BFI, - ProfileSummaryInfo *PSI, LoopInfo *LI, const InstCombineOptions &Opts) { + BranchProbabilityInfo *BPI, ProfileSummaryInfo *PSI, LoopInfo *LI, + const InstCombineOptions &Opts) { auto &DL = F.getParent()->getDataLayout(); /// Builder - This is an IRBuilder that automatically inserts new @@ -5286,7 +5297,7 @@ static bool combineInstructionsOverFunction( << F.getName() << "\n"); InstCombinerImpl IC(Worklist, Builder, F.hasMinSize(), AA, AC, TLI, TTI, DT, - ORE, BFI, PSI, DL, LI); + ORE, BFI, BPI, PSI, DL, LI); IC.MaxArraySizeForCombine = MaxArraySize; bool MadeChangeInThisIteration = IC.prepareWorklist(F, RPOT); MadeChangeInThisIteration |= IC.run(); @@ -5347,9 +5358,10 @@ PreservedAnalyses InstCombinePass::run(Function &F, MAMProxy.getCachedResult(*F.getParent()); auto *BFI = (PSI && PSI->hasProfileSummary()) ? &AM.getResult(F) : nullptr; + auto *BPI = AM.getCachedResult(F); if (!combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, TTI, DT, ORE, - BFI, PSI, LI, Options)) + BFI, BPI, PSI, LI, Options)) // No changes, all analyses are preserved. return PreservedAnalyses::all(); @@ -5396,9 +5408,14 @@ bool InstructionCombiningPass::runOnFunction(Function &F) { (PSI && PSI->hasProfileSummary()) ? &getAnalysis().getBFI() : nullptr; + BranchProbabilityInfo *BPI = nullptr; + if (auto *WrapperPass = + getAnalysisIfAvailable()) + BPI = &WrapperPass->getBPI(); return combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, TTI, DT, ORE, - BFI, PSI, LI, InstCombineOptions()); + BFI, BPI, PSI, LI, + InstCombineOptions()); } char InstructionCombiningPass::ID = 0; diff --git a/llvm/test/Transforms/InstCombine/update-bpi.ll b/llvm/test/Transforms/InstCombine/update-bpi.ll index 190a686c8f07..fadb2ab16bff 100644 --- a/llvm/test/Transforms/InstCombine/update-bpi.ll +++ b/llvm/test/Transforms/InstCombine/update-bpi.ll @@ -6,8 +6,8 @@ ; CHECK-NEXT: edge %entry -> %bb2 probability is 0x79e79e7a / 0x80000000 = 95.24% [HOT edge] ; CHECK-NEXT: Printing analysis 'Branch Probability Analysis' for function 'invert_cond': ; CHECK-NEXT: ---- Branch Probabilities ---- -; CHECK-NEXT: edge %entry -> %bb2 probability is 0x06186186 / 0x80000000 = 4.76% -; CHECK-NEXT: edge %entry -> %bb1 probability is 0x79e79e7a / 0x80000000 = 95.24% [HOT edge] +; CHECK-NEXT: edge %entry -> %bb2 probability is 0x79e79e7a / 0x80000000 = 95.24% [HOT edge] +; CHECK-NEXT: edge %entry -> %bb1 probability is 0x06186186 / 0x80000000 = 4.76% define i32 @invert_cond(ptr %p) { ; CHECK-LABEL: define i32 @invert_cond( -- GitLab From 5a1a5226b578ec7f123f67efd4e24e39fecd11d7 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <1802579+farzonl@users.noreply.github.com> Date: Sat, 20 Apr 2024 11:13:53 -0400 Subject: [PATCH 084/357] [SPIRV][HLSL] Add mad intrinsic lowering for spirv (#89130) - `clang/lib/CodeGen/CGBuiltin.cpp` - Add a generic mull add implementation. Make DXIL implementation tied to target. resolves #88944 --- clang/lib/CodeGen/CGBuiltin.cpp | 26 +- clang/test/CodeGenHLSL/builtins/mad.hlsl | 240 ++++++++------ llvm/test/CodeGen/DirectX/fmad.ll | 12 +- .../CodeGen/SPIRV/hlsl-intrinsics/fmad.ll | 12 +- .../CodeGen/SPIRV/hlsl-intrinsics/imad.ll | 302 ++++++++++++++++++ 5 files changed, 479 insertions(+), 113 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/imad.ll diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4ab844d206e4..afe2de5d00ac 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18296,20 +18296,28 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Value *M = EmitScalarExpr(E->getArg(0)); Value *A = EmitScalarExpr(E->getArg(1)); Value *B = EmitScalarExpr(E->getArg(2)); - if (E->getArg(0)->getType()->hasFloatingRepresentation()) { + if (E->getArg(0)->getType()->hasFloatingRepresentation()) return Builder.CreateIntrinsic( /*ReturnType*/ M->getType(), Intrinsic::fmuladd, - ArrayRef{M, A, B}, nullptr, "dx.fmad"); - } + ArrayRef{M, A, B}, nullptr, "hlsl.fmad"); + if (E->getArg(0)->getType()->hasSignedIntegerRepresentation()) { - return Builder.CreateIntrinsic( - /*ReturnType*/ M->getType(), Intrinsic::dx_imad, - ArrayRef{M, A, B}, nullptr, "dx.imad"); + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil) + return Builder.CreateIntrinsic( + /*ReturnType*/ M->getType(), Intrinsic::dx_imad, + ArrayRef{M, A, B}, nullptr, "dx.imad"); + + Value *Mul = Builder.CreateNSWMul(M, A); + return Builder.CreateNSWAdd(Mul, B); } assert(E->getArg(0)->getType()->hasUnsignedIntegerRepresentation()); - return Builder.CreateIntrinsic( - /*ReturnType=*/M->getType(), Intrinsic::dx_umad, - ArrayRef{M, A, B}, nullptr, "dx.umad"); + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil) + return Builder.CreateIntrinsic( + /*ReturnType=*/M->getType(), Intrinsic::dx_umad, + ArrayRef{M, A, B}, nullptr, "dx.umad"); + + Value *Mul = Builder.CreateNUWMul(M, A); + return Builder.CreateNUWAdd(Mul, B); } case Builtin::BI__builtin_hlsl_elementwise_rcp: { Value *Op0 = EmitScalarExpr(E->getArg(0)); diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl index 749eac6d6473..bd4f38067a5c 100644 --- a/clang/test/CodeGenHLSL/builtins/mad.hlsl +++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl @@ -1,182 +1,238 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF + +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_CHECK #ifdef __HLSL_ENABLE_16_BIT -// NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %0, i16 %1, i16 %2) -// NATIVE_HALF: ret i16 %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %0, i16 %1, i16 %2) +// DXIL_NATIVE_HALF: ret i16 %dx.umad +// SPIR_NATIVE_HALF: mul nuw i16 %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw i16 %{{.*}}, %{{.*}} uint16_t test_mad_uint16_t(uint16_t p0, uint16_t p1, uint16_t p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.umad = call <2 x i16> @llvm.dx.umad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) -// NATIVE_HALF: ret <2 x i16> %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call <2 x i16> @llvm.dx.umad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) +// DXIL_NATIVE_HALF: ret <2 x i16> %dx.umad +// SPIR_NATIVE_HALF: mul nuw <2 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw <2 x i16> %{{.*}}, %{{.*}} uint16_t2 test_mad_uint16_t2(uint16_t2 p0, uint16_t2 p1, uint16_t2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.umad = call <3 x i16> @llvm.dx.umad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) -// NATIVE_HALF: ret <3 x i16> %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call <3 x i16> @llvm.dx.umad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) +// DXIL_NATIVE_HALF: ret <3 x i16> %dx.umad +// SPIR_NATIVE_HALF: mul nuw <3 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw <3 x i16> %{{.*}}, %{{.*}} uint16_t3 test_mad_uint16_t3(uint16_t3 p0, uint16_t3 p1, uint16_t3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.umad = call <4 x i16> @llvm.dx.umad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) -// NATIVE_HALF: ret <4 x i16> %dx.umad +// DXIL_NATIVE_HALF: %dx.umad = call <4 x i16> @llvm.dx.umad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) +// DXIL_NATIVE_HALF: ret <4 x i16> %dx.umad +// SPIR_NATIVE_HALF: mul nuw <4 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nuw <4 x i16> %{{.*}}, %{{.*}} uint16_t4 test_mad_uint16_t4(uint16_t4 p0, uint16_t4 p1, uint16_t4 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %0, i16 %1, i16 %2) -// NATIVE_HALF: ret i16 %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %0, i16 %1, i16 %2) +// DXIL_NATIVE_HALF: ret i16 %dx.imad +// SPIR_NATIVE_HALF: mul nsw i16 %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw i16 %{{.*}}, %{{.*}} int16_t test_mad_int16_t(int16_t p0, int16_t p1, int16_t p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call <2 x i16> @llvm.dx.imad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) -// NATIVE_HALF: ret <2 x i16> %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call <2 x i16> @llvm.dx.imad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2) +// DXIL_NATIVE_HALF: ret <2 x i16> %dx.imad +// SPIR_NATIVE_HALF: mul nsw <2 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw <2 x i16> %{{.*}}, %{{.*}} int16_t2 test_mad_int16_t2(int16_t2 p0, int16_t2 p1, int16_t2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call <3 x i16> @llvm.dx.imad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) -// NATIVE_HALF: ret <3 x i16> %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call <3 x i16> @llvm.dx.imad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2) +// DXIL_NATIVE_HALF: ret <3 x i16> %dx.imad +// SPIR_NATIVE_HALF: mul nsw <3 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw <3 x i16> %{{.*}}, %{{.*}} int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.imad = call <4 x i16> @llvm.dx.imad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) -// NATIVE_HALF: ret <4 x i16> %dx.imad +// DXIL_NATIVE_HALF: %dx.imad = call <4 x i16> @llvm.dx.imad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2) +// DXIL_NATIVE_HALF: ret <4 x i16> %dx.imad +// SPIR_NATIVE_HALF: mul nsw <4 x i16> %{{.*}}, %{{.*}} +// SPIR_NATIVE_HALF: add nsw <4 x i16> %{{.*}}, %{{.*}} int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p0, p1, p2); } #endif // __HLSL_ENABLE_16_BIT -// NATIVE_HALF: %dx.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) -// NATIVE_HALF: ret half %dx.fmad -// NO_HALF: %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) -// NO_HALF: ret float %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) +// NATIVE_HALF: ret half %hlsl.fmad +// NO_HALF: %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +// NO_HALF: ret float %hlsl.fmad half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.fmad = call <2 x half> @llvm.fmuladd.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) -// NATIVE_HALF: ret <2 x half> %dx.fmad -// NO_HALF: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// NO_HALF: ret <2 x float> %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call <2 x half> @llvm.fmuladd.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// NATIVE_HALF: ret <2 x half> %hlsl.fmad +// NO_HALF: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// NO_HALF: ret <2 x float> %hlsl.fmad half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.fmad = call <3 x half> @llvm.fmuladd.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// NATIVE_HALF: ret <3 x half> %dx.fmad -// NO_HALF: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// NO_HALF: ret <3 x float> %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call <3 x half> @llvm.fmuladd.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// NATIVE_HALF: ret <3 x half> %hlsl.fmad +// NO_HALF: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// NO_HALF: ret <3 x float> %hlsl.fmad half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); } -// NATIVE_HALF: %dx.fmad = call <4 x half> @llvm.fmuladd.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) -// NATIVE_HALF: ret <4 x half> %dx.fmad -// NO_HALF: %dx.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// NO_HALF: ret <4 x float> %dx.fmad +// NATIVE_HALF: %hlsl.fmad = call <4 x half> @llvm.fmuladd.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// NATIVE_HALF: ret <4 x half> %hlsl.fmad +// NO_HALF: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// NO_HALF: ret <4 x float> %hlsl.fmad half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) -// CHECK: ret float %dx.fmad +// CHECK: %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) +// CHECK: ret float %hlsl.fmad float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.fmad float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) -// CHECK: ret double %dx.fmad +// CHECK: %hlsl.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) +// CHECK: ret double %hlsl.fmad double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %0, <2 x double> %1, <2 x double> %2) -// CHECK: ret <2 x double> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %0, <2 x double> %1, <2 x double> %2) +// CHECK: ret <2 x double> %hlsl.fmad double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <3 x double> @llvm.fmuladd.v3f64(<3 x double> %0, <3 x double> %1, <3 x double> %2) -// CHECK: ret <3 x double> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x double> @llvm.fmuladd.v3f64(<3 x double> %0, <3 x double> %1, <3 x double> %2) +// CHECK: ret <3 x double> %hlsl.fmad double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %0, <4 x double> %1, <4 x double> %2) -// CHECK: ret <4 x double> %dx.fmad +// CHECK: %hlsl.fmad = call <4 x double> @llvm.fmuladd.v4f64(<4 x double> %0, <4 x double> %1, <4 x double> %2) +// CHECK: ret <4 x double> %hlsl.fmad double4 test_mad_double4(double4 p0, double4 p1, double4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %0, i32 %1, i32 %2) -// CHECK: ret i32 %dx.imad +// DXIL_CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %0, i32 %1, i32 %2) +// DXIL_CHECK: ret i32 %dx.imad +// SPIR_CHECK: mul nsw i32 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw i32 %{{.*}}, %{{.*}} int test_mad_int(int p0, int p1, int p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <2 x i32> @llvm.dx.imad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) -// CHECK: ret <2 x i32> %dx.imad +// DXIL_CHECK: %dx.imad = call <2 x i32> @llvm.dx.imad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) +// DXIL_CHECK: ret <2 x i32> %dx.imad +// SPIR_CHECK: mul nsw <2 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <2 x i32> %{{.*}}, %{{.*}} int2 test_mad_int2(int2 p0, int2 p1, int2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <3 x i32> @llvm.dx.imad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) -// CHECK: ret <3 x i32> %dx.imad +// DXIL_CHECK: %dx.imad = call <3 x i32> @llvm.dx.imad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) +// DXIL_CHECK: ret <3 x i32> %dx.imad +// SPIR_CHECK: mul nsw <3 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <3 x i32> %{{.*}}, %{{.*}} int3 test_mad_int3(int3 p0, int3 p1, int3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <4 x i32> @llvm.dx.imad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) -// CHECK: ret <4 x i32> %dx.imad +// DXIL_CHECK: %dx.imad = call <4 x i32> @llvm.dx.imad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) +// DXIL_CHECK: ret <4 x i32> %dx.imad +// SPIR_CHECK: mul nsw <4 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <4 x i32> %{{.*}}, %{{.*}} int4 test_mad_int4(int4 p0, int4 p1, int4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %0, i64 %1, i64 %2) -// CHECK: ret i64 %dx.imad +// DXIL_CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %0, i64 %1, i64 %2) +// DXIL_CHECK: ret i64 %dx.imad +// SPIR_CHECK: mul nsw i64 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw i64 %{{.*}}, %{{.*}} int64_t test_mad_int64_t(int64_t p0, int64_t p1, int64_t p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <2 x i64> @llvm.dx.imad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) -// CHECK: ret <2 x i64> %dx.imad +// DXIL_CHECK: %dx.imad = call <2 x i64> @llvm.dx.imad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) +// DXIL_CHECK: ret <2 x i64> %dx.imad +// SPIR_CHECK: mul nsw <2 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <2 x i64> %{{.*}}, %{{.*}} int64_t2 test_mad_int64_t2(int64_t2 p0, int64_t2 p1, int64_t2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <3 x i64> @llvm.dx.imad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) -// CHECK: ret <3 x i64> %dx.imad +// DXIL_CHECK: %dx.imad = call <3 x i64> @llvm.dx.imad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) +// DXIL_CHECK: ret <3 x i64> %dx.imad +// SPIR_CHECK: mul nsw <3 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <3 x i64> %{{.*}}, %{{.*}} int64_t3 test_mad_int64_t3(int64_t3 p0, int64_t3 p1, int64_t3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.imad = call <4 x i64> @llvm.dx.imad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) -// CHECK: ret <4 x i64> %dx.imad +// DXIL_CHECK: %dx.imad = call <4 x i64> @llvm.dx.imad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) +// DXIL_CHECK: ret <4 x i64> %dx.imad +// SPIR_CHECK: mul nsw <4 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nsw <4 x i64> %{{.*}}, %{{.*}} int64_t4 test_mad_int64_t4(int64_t4 p0, int64_t4 p1, int64_t4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %0, i32 %1, i32 %2) -// CHECK: ret i32 %dx.umad +// DXIL_CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %0, i32 %1, i32 %2) +// DXIL_CHECK: ret i32 %dx.umad +// SPIR_CHECK: mul nuw i32 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw i32 %{{.*}}, %{{.*}} uint test_mad_uint(uint p0, uint p1, uint p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <2 x i32> @llvm.dx.umad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) -// CHECK: ret <2 x i32> %dx.umad +// DXIL_CHECK: %dx.umad = call <2 x i32> @llvm.dx.umad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2) +// DXIL_CHECK: ret <2 x i32> %dx.umad +// SPIR_CHECK: mul nuw <2 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <2 x i32> %{{.*}}, %{{.*}} uint2 test_mad_uint2(uint2 p0, uint2 p1, uint2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <3 x i32> @llvm.dx.umad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) -// CHECK: ret <3 x i32> %dx.umad +// DXIL_CHECK: %dx.umad = call <3 x i32> @llvm.dx.umad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2) +// DXIL_CHECK: ret <3 x i32> %dx.umad +// SPIR_CHECK: mul nuw <3 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <3 x i32> %{{.*}}, %{{.*}} uint3 test_mad_uint3(uint3 p0, uint3 p1, uint3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <4 x i32> @llvm.dx.umad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) -// CHECK: ret <4 x i32> %dx.umad +// DXIL_CHECK: %dx.umad = call <4 x i32> @llvm.dx.umad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) +// DXIL_CHECK: ret <4 x i32> %dx.umad +// SPIR_CHECK: mul nuw <4 x i32> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <4 x i32> %{{.*}}, %{{.*}} uint4 test_mad_uint4(uint4 p0, uint4 p1, uint4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %0, i64 %1, i64 %2) -// CHECK: ret i64 %dx.umad +// DXIL_CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %0, i64 %1, i64 %2) +// DXIL_CHECK: ret i64 %dx.umad +// SPIR_CHECK: mul nuw i64 %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw i64 %{{.*}}, %{{.*}} uint64_t test_mad_uint64_t(uint64_t p0, uint64_t p1, uint64_t p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <2 x i64> @llvm.dx.umad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) -// CHECK: ret <2 x i64> %dx.umad +// DXIL_CHECK: %dx.umad = call <2 x i64> @llvm.dx.umad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) +// DXIL_CHECK: ret <2 x i64> %dx.umad +// SPIR_CHECK: mul nuw <2 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <2 x i64> %{{.*}}, %{{.*}} uint64_t2 test_mad_uint64_t2(uint64_t2 p0, uint64_t2 p1, uint64_t2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <3 x i64> @llvm.dx.umad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) -// CHECK: ret <3 x i64> %dx.umad +// DXIL_CHECK: %dx.umad = call <3 x i64> @llvm.dx.umad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2) +// DXIL_CHECK: ret <3 x i64> %dx.umad +// SPIR_CHECK: mul nuw <3 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <3 x i64> %{{.*}}, %{{.*}} uint64_t3 test_mad_uint64_t3(uint64_t3 p0, uint64_t3 p1, uint64_t3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.umad = call <4 x i64> @llvm.dx.umad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) -// CHECK: ret <4 x i64> %dx.umad +// DXIL_CHECK: %dx.umad = call <4 x i64> @llvm.dx.umad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2) +// DXIL_CHECK: ret <4 x i64> %dx.umad +// SPIR_CHECK: mul nuw <4 x i64> %{{.*}}, %{{.*}} +// SPIR_CHECK: add nuw <4 x i64> %{{.*}}, %{{.*}} uint64_t4 test_mad_uint64_t4(uint64_t4 p0, uint64_t4 p1, uint64_t4 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2_splat(float p0, float2 p1, float2 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3_splat(float p0, float3 p1, float3 p2) { return mad(p0, p1, p2); } -// CHECK: %dx.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.fmad float4 test_mad_float4_splat(float p0, float4 p1, float4 p2) { return mad(p0, p1, p2); } // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %dx.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) -// CHECK: ret <2 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// CHECK: ret <2 x float> %hlsl.fmad float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) { return mad(p0, p1, p2); } @@ -184,8 +240,8 @@ float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) { // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %dx.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) -// CHECK: ret <3 x float> %dx.fmad +// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// CHECK: ret <3 x float> %hlsl.fmad float3 test_mad_float3_int_splat(float3 p0, float3 p1, int p2) { return mad(p0, p1, p2); } diff --git a/llvm/test/CodeGen/DirectX/fmad.ll b/llvm/test/CodeGen/DirectX/fmad.ll index 693e237e70dc..e1f4e5cd50c4 100644 --- a/llvm/test/CodeGen/DirectX/fmad.ll +++ b/llvm/test/CodeGen/DirectX/fmad.ll @@ -21,8 +21,8 @@ entry: %0 = load half, ptr %p0.addr, align 2 %1 = load half, ptr %p1.addr, align 2 %2 = load half, ptr %p2.addr, align 2 - %dx.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) - ret half %dx.fmad + %hlsl.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2) + ret half %hlsl.fmad } ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) @@ -40,8 +40,8 @@ entry: %0 = load float, ptr %p0.addr, align 4 %1 = load float, ptr %p1.addr, align 4 %2 = load float, ptr %p2.addr, align 4 - %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) - ret float %dx.fmad + %hlsl.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2) + ret float %hlsl.fmad } ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) @@ -59,8 +59,8 @@ entry: %0 = load double, ptr %p0.addr, align 8 %1 = load double, ptr %p1.addr, align 8 %2 = load double, ptr %p2.addr, align 8 - %dx.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) - ret double %dx.fmad + %hlsl.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2) + ret double %hlsl.fmad } ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll index a3fec10a9e4b..ce9b8f09daea 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll @@ -6,22 +6,22 @@ define noundef half @fmad_half(half noundef %a, half noundef %b, half noundef %c) #0 { entry: ; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Fma %[[#]] %[[#]] %[[#]] - %dx.fmad = call half @llvm.fmuladd.f16(half %a, half %b, half %c) - ret half %dx.fmad + %hlsl.fmad = call half @llvm.fmuladd.f16(half %a, half %b, half %c) + ret half %hlsl.fmad } define noundef float @fmad_float(float noundef %a, float noundef %b, float noundef %c) #0 { entry: ; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Fma %[[#]] %[[#]] %[[#]] - %dx.fmad = call float @llvm.fmuladd.f32(float %a, float %b, float %c) - ret float %dx.fmad + %hlsl.fmad = call float @llvm.fmuladd.f32(float %a, float %b, float %c) + ret float %hlsl.fmad } define noundef double @fmad_double(double noundef %a, double noundef %b, double noundef %c) { entry: ; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Fma %[[#]] %[[#]] %[[#]] - %dx.fmad = call double @llvm.fmuladd.f64(double %a, double %b, double %c) - ret double %dx.fmad + %hlsl.fmad = call double @llvm.fmuladd.f64(double %a, double %b, double %c) + ret double %hlsl.fmad } declare half @llvm.fmuladd.f16(half, half, half) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/imad.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/imad.ll new file mode 100644 index 000000000000..b854412b6ec1 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/imad.ll @@ -0,0 +1,302 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: %[[#int_16:]] = OpTypeInt 16 0 +; CHECK-DAG: %[[#vec2_16:]] = OpTypeVector %[[#int_16]] 2 +; CHECK-DAG: %[[#vec3_16:]] = OpTypeVector %[[#int_16]] 3 +; CHECK-DAG: %[[#vec4_16:]] = OpTypeVector %[[#int_16]] 4 +; CHECK-DAG: %[[#int_32:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#vec2_32:]] = OpTypeVector %[[#int_32]] 2 +; CHECK-DAG: %[[#vec3_32:]] = OpTypeVector %[[#int_32]] 3 +; CHECK-DAG: %[[#vec4_32:]] = OpTypeVector %[[#int_32]] 4 +; CHECK-DAG: %[[#int_64:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#vec2_64:]] = OpTypeVector %[[#int_64]] 2 +; CHECK-DAG: %[[#vec3_64:]] = OpTypeVector %[[#int_64]] 3 +; CHECK-DAG: %[[#vec4_64:]] = OpTypeVector %[[#int_64]] 4 + +define spir_func noundef i16 @test_mad_uint16_t(i16 noundef %p0, i16 noundef %p1, i16 noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#int_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#int_16]] %[[#mul]] %[[#arg2]] + %3 = mul nuw i16 %p0, %p1 + %4 = add nuw i16 %3, %p2 + ret i16 %4 +} + +define spir_func noundef <2 x i16> @test_mad_uint16_t2(<2 x i16> noundef %p0, <2 x i16> noundef %p1, <2 x i16> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec2_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec2_16]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <2 x i16> %p0, %p1 + %4 = add nuw <2 x i16> %3, %p2 + ret <2 x i16> %4 +} + +define spir_func noundef <3 x i16> @test_mad_uint16_t3(<3 x i16> noundef %p0, <3 x i16> noundef %p1, <3 x i16> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec3_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec3_16]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <3 x i16> %p0, %p1 + %4 = add nuw <3 x i16> %3, %p2 + ret <3 x i16> %4 +} + +define spir_func noundef <4 x i16> @test_mad_uint16_t4(<4 x i16> noundef %p0, <4 x i16> noundef %p1, <4 x i16> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec4_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec4_16]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <4 x i16> %p0, %p1 + %4 = add nuw <4 x i16> %3, %p2 + ret <4 x i16> %4 +} + +define spir_func noundef i16 @test_mad_int16_t(i16 noundef %p0, i16 noundef %p1, i16 noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#int_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#int_16]] %[[#mul]] %[[#arg2]] + %3 = mul nsw i16 %p0, %p1 + %4 = add nsw i16 %3, %p2 + ret i16 %4 +} + +define spir_func noundef <2 x i16> @test_mad_int16_t2(<2 x i16> noundef %p0, <2 x i16> noundef %p1, <2 x i16> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec2_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec2_16]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <2 x i16> %p0, %p1 + %4 = add nsw <2 x i16> %3, %p2 + ret <2 x i16> %4 +} + +define spir_func noundef <3 x i16> @test_mad_int16_t3(<3 x i16> noundef %p0, <3 x i16> noundef %p1, <3 x i16> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec3_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec3_16]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <3 x i16> %p0, %p1 + %4 = add nsw <3 x i16> %3, %p2 + ret <3 x i16> %4 +} + +define spir_func noundef <4 x i16> @test_mad_int16_t4(<4 x i16> noundef %p0, <4 x i16> noundef %p1, <4 x i16> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec4_16]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec4_16]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <4 x i16> %p0, %p1 + %4 = add nsw <4 x i16> %3, %p2 + ret <4 x i16> %4 +} +define spir_func noundef i32 @test_mad_int(i32 noundef %p0, i32 noundef %p1, i32 noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#int_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#int_32]] %[[#mul]] %[[#arg2]] + %3 = mul nsw i32 %p0, %p1 + %4 = add nsw i32 %3, %p2 + ret i32 %4 +} + +define spir_func noundef <2 x i32> @test_mad_int2(<2 x i32> noundef %p0, <2 x i32> noundef %p1, <2 x i32> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec2_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec2_32]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <2 x i32> %p0, %p1 + %4 = add nsw <2 x i32> %3, %p2 + ret <2 x i32> %4 +} + +define spir_func noundef <3 x i32> @test_mad_int3(<3 x i32> noundef %p0, <3 x i32> noundef %p1, <3 x i32> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec3_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec3_32]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <3 x i32> %p0, %p1 + %4 = add nsw <3 x i32> %3, %p2 + ret <3 x i32> %4 +} + +define spir_func noundef <4 x i32> @test_mad_int4(<4 x i32> noundef %p0, <4 x i32> noundef %p1, <4 x i32> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec4_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec4_32]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <4 x i32> %p0, %p1 + %4 = add nsw <4 x i32> %3, %p2 + ret <4 x i32> %4 +} + +define spir_func noundef i64 @test_mad_int64_t(i64 noundef %p0, i64 noundef %p1, i64 noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#int_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#int_64]] %[[#mul]] %[[#arg2]] + %3 = mul nsw i64 %p0, %p1 + %4 = add nsw i64 %3, %p2 + ret i64 %4 +} + +define spir_func noundef <2 x i64> @test_mad_int64_t2(<2 x i64> noundef %p0, <2 x i64> noundef %p1, <2 x i64> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec2_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec2_64]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <2 x i64> %p0, %p1 + %4 = add nsw <2 x i64> %3, %p2 + ret <2 x i64> %4 +} + +define spir_func noundef <3 x i64> @test_mad_int64_t3(<3 x i64> noundef %p0, <3 x i64> noundef %p1, <3 x i64> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec3_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec3_64]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <3 x i64> %p0, %p1 + %4 = add nsw <3 x i64> %3, %p2 + ret <3 x i64> %4 +} + +define spir_func noundef <4 x i64> @test_mad_int64_t4(<4 x i64> noundef %p0, <4 x i64> noundef %p1, <4 x i64> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec4_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec4_64]] %[[#mul]] %[[#arg2]] + %3 = mul nsw <4 x i64> %p0, %p1 + %4 = add nsw <4 x i64> %3, %p2 + ret <4 x i64> %4 +} + +define spir_func noundef i32 @test_mad_uint(i32 noundef %p0, i32 noundef %p1, i32 noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#int_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#int_32]] %[[#mul]] %[[#arg2]] + %3 = mul nuw i32 %p0, %p1 + %4 = add nuw i32 %3, %p2 + ret i32 %4 +} + +define spir_func noundef <2 x i32> @test_mad_uint2(<2 x i32> noundef %p0, <2 x i32> noundef %p1, <2 x i32> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec2_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec2_32]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <2 x i32> %p0, %p1 + %4 = add nuw <2 x i32> %3, %p2 + ret <2 x i32> %4 +} + +define spir_func noundef <3 x i32> @test_mad_uint3(<3 x i32> noundef %p0, <3 x i32> noundef %p1, <3 x i32> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec3_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec3_32]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <3 x i32> %p0, %p1 + %4 = add nuw <3 x i32> %3, %p2 + ret <3 x i32> %4 +} + +define spir_func noundef <4 x i32> @test_mad_uint4(<4 x i32> noundef %p0, <4 x i32> noundef %p1, <4 x i32> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec4_32]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec4_32]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <4 x i32> %p0, %p1 + %4 = add nuw <4 x i32> %3, %p2 + ret <4 x i32> %4 +} + +define spir_func noundef i64 @test_mad_uint64_t(i64 noundef %p0, i64 noundef %p1, i64 noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#int_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#int_64]] %[[#mul]] %[[#arg2]] + %3 = mul nuw i64 %p0, %p1 + %4 = add nuw i64 %3, %p2 + ret i64 %4 +} + +define spir_func noundef <2 x i64> @test_mad_uint64_t2(<2 x i64> noundef %p0, <2 x i64> noundef %p1, <2 x i64> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec2_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec2_64]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <2 x i64> %p0, %p1 + %4 = add nuw <2 x i64> %3, %p2 + ret <2 x i64> %4 +} + +define spir_func noundef <3 x i64> @test_mad_uint64_t3(<3 x i64> noundef %p0, <3 x i64> noundef %p1, <3 x i64> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec3_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec3_64]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <3 x i64> %p0, %p1 + %4 = add nuw <3 x i64> %3, %p2 + ret <3 x i64> %4 +} + +define spir_func noundef <4 x i64> @test_mad_uint64_t4(<4 x i64> noundef %p0, <4 x i64> noundef %p1, <4 x i64> noundef %p2) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#mul:]] = OpIMul %[[#vec4_64]] %[[#arg0]] %[[#arg1]] + ; CHECK: OpIAdd %[[#vec4_64]] %[[#mul]] %[[#arg2]] + %3 = mul nuw <4 x i64> %p0, %p1 + %4 = add nuw <4 x i64> %3, %p2 + ret <4 x i64> %4 +} -- GitLab From 87d36c5d8285b61f3e39b3f63d5eced733bd9d3e Mon Sep 17 00:00:00 2001 From: David Green Date: Sat, 20 Apr 2024 15:52:09 +0100 Subject: [PATCH 085/357] [AArch64] Add phase ordering tests for some basic interleaving vectorization patterns. NFC --- .../AArch64/interleavevectorization.ll | 920 ++++++++++++++++++ 1 file changed, 920 insertions(+) create mode 100644 llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll new file mode 100644 index 000000000000..b49c0ad99766 --- /dev/null +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll @@ -0,0 +1,920 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes='default' -S -o - %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "aarch64" + +; for(int i =0; i < 1024; i+=4) { +; x[i] += y[i]; +; x[i+1] += y[i+1]; +; x[i+2] += y[i+2]; +; x[i+3] += y[i+3]; +; } +define void @add4(ptr noalias noundef %x, ptr noalias noundef %y, i32 noundef %n) { +; CHECK-LABEL: @add4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 -6 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i16, ptr [[Y:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <32 x i16>, ptr [[TMP0]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC24:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 +; CHECK-NEXT: [[TMP2:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP6]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP9:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i16> [[TMP9]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP8]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP5]], <16 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> [[TMP10]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP11]], <16 x i16> [[TMP12]], <32 x i32> +; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP13]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %x.addr = alloca ptr, align 8 + %y.addr = alloca ptr, align 8 + %n.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %x, ptr %x.addr, align 8 + store ptr %y, ptr %y.addr, align 8 + store i32 %n, ptr %n.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %1 = load ptr, ptr %y.addr, align 8 + %2 = load i32, ptr %i, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds i16, ptr %1, i64 %idxprom + %3 = load i16, ptr %arrayidx, align 2 + %conv = sext i16 %3 to i32 + %4 = load ptr, ptr %x.addr, align 8 + %5 = load i32, ptr %i, align 4 + %idxprom1 = sext i32 %5 to i64 + %arrayidx2 = getelementptr inbounds i16, ptr %4, i64 %idxprom1 + %6 = load i16, ptr %arrayidx2, align 2 + %conv3 = sext i16 %6 to i32 + %add = add nsw i32 %conv3, %conv + %conv4 = trunc i32 %add to i16 + store i16 %conv4, ptr %arrayidx2, align 2 + %7 = load ptr, ptr %y.addr, align 8 + %8 = load i32, ptr %i, align 4 + %add5 = add nsw i32 %8, 1 + %idxprom6 = sext i32 %add5 to i64 + %arrayidx7 = getelementptr inbounds i16, ptr %7, i64 %idxprom6 + %9 = load i16, ptr %arrayidx7, align 2 + %conv8 = sext i16 %9 to i32 + %10 = load ptr, ptr %x.addr, align 8 + %11 = load i32, ptr %i, align 4 + %add9 = add nsw i32 %11, 1 + %idxprom10 = sext i32 %add9 to i64 + %arrayidx11 = getelementptr inbounds i16, ptr %10, i64 %idxprom10 + %12 = load i16, ptr %arrayidx11, align 2 + %conv12 = sext i16 %12 to i32 + %add13 = add nsw i32 %conv12, %conv8 + %conv14 = trunc i32 %add13 to i16 + store i16 %conv14, ptr %arrayidx11, align 2 + %13 = load ptr, ptr %y.addr, align 8 + %14 = load i32, ptr %i, align 4 + %add15 = add nsw i32 %14, 2 + %idxprom16 = sext i32 %add15 to i64 + %arrayidx17 = getelementptr inbounds i16, ptr %13, i64 %idxprom16 + %15 = load i16, ptr %arrayidx17, align 2 + %conv18 = sext i16 %15 to i32 + %16 = load ptr, ptr %x.addr, align 8 + %17 = load i32, ptr %i, align 4 + %add19 = add nsw i32 %17, 2 + %idxprom20 = sext i32 %add19 to i64 + %arrayidx21 = getelementptr inbounds i16, ptr %16, i64 %idxprom20 + %18 = load i16, ptr %arrayidx21, align 2 + %conv22 = sext i16 %18 to i32 + %add23 = add nsw i32 %conv22, %conv18 + %conv24 = trunc i32 %add23 to i16 + store i16 %conv24, ptr %arrayidx21, align 2 + %19 = load ptr, ptr %y.addr, align 8 + %20 = load i32, ptr %i, align 4 + %add25 = add nsw i32 %20, 3 + %idxprom26 = sext i32 %add25 to i64 + %arrayidx27 = getelementptr inbounds i16, ptr %19, i64 %idxprom26 + %21 = load i16, ptr %arrayidx27, align 2 + %conv28 = sext i16 %21 to i32 + %22 = load ptr, ptr %x.addr, align 8 + %23 = load i32, ptr %i, align 4 + %add29 = add nsw i32 %23, 3 + %idxprom30 = sext i32 %add29 to i64 + %arrayidx31 = getelementptr inbounds i16, ptr %22, i64 %idxprom30 + %24 = load i16, ptr %arrayidx31, align 2 + %conv32 = sext i16 %24 to i32 + %add33 = add nsw i32 %conv32, %conv28 + %conv34 = trunc i32 %add33 to i16 + store i16 %conv34, ptr %arrayidx31, align 2 + br label %for.inc + +for.inc: + %25 = load i32, ptr %i, align 4 + %add35 = add nsw i32 %25, 4 + store i32 %add35, ptr %i, align 4 + br label %for.cond + +for.end: + ret void +} + +; for(int i =0; i < 1024; i+=4) { +; x[i] += y[i]; +; x[i+1] -= y[i+1]; +; x[i+2] += y[i+2]; +; x[i+3] -= y[i+3]; +; } +define void @addsubs(ptr noalias noundef %x, ptr noundef %y, i32 noundef %n) { +; CHECK-LABEL: @addsubs( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 -6 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i16, ptr [[Y:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <32 x i16>, ptr [[TMP0]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC24:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 +; CHECK-NEXT: [[TMP2:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP6]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP9:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i16> [[TMP9]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP8]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP5]], <16 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> [[TMP10]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP11]], <16 x i16> [[TMP12]], <32 x i32> +; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP13]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %x.addr = alloca ptr, align 8 + %y.addr = alloca ptr, align 8 + %n.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %x, ptr %x.addr, align 8 + store ptr %y, ptr %y.addr, align 8 + store i32 %n, ptr %n.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %1 = load ptr, ptr %y.addr, align 8 + %2 = load i32, ptr %i, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds i16, ptr %1, i64 %idxprom + %3 = load i16, ptr %arrayidx, align 2 + %conv = sext i16 %3 to i32 + %4 = load ptr, ptr %x.addr, align 8 + %5 = load i32, ptr %i, align 4 + %idxprom1 = sext i32 %5 to i64 + %arrayidx2 = getelementptr inbounds i16, ptr %4, i64 %idxprom1 + %6 = load i16, ptr %arrayidx2, align 2 + %conv3 = sext i16 %6 to i32 + %add = add nsw i32 %conv3, %conv + %conv4 = trunc i32 %add to i16 + store i16 %conv4, ptr %arrayidx2, align 2 + %7 = load ptr, ptr %y.addr, align 8 + %8 = load i32, ptr %i, align 4 + %add5 = add nsw i32 %8, 1 + %idxprom6 = sext i32 %add5 to i64 + %arrayidx7 = getelementptr inbounds i16, ptr %7, i64 %idxprom6 + %9 = load i16, ptr %arrayidx7, align 2 + %conv8 = sext i16 %9 to i32 + %10 = load ptr, ptr %x.addr, align 8 + %11 = load i32, ptr %i, align 4 + %add9 = add nsw i32 %11, 1 + %idxprom10 = sext i32 %add9 to i64 + %arrayidx11 = getelementptr inbounds i16, ptr %10, i64 %idxprom10 + %12 = load i16, ptr %arrayidx11, align 2 + %conv12 = sext i16 %12 to i32 + %sub = sub nsw i32 %conv12, %conv8 + %conv13 = trunc i32 %sub to i16 + store i16 %conv13, ptr %arrayidx11, align 2 + %13 = load ptr, ptr %y.addr, align 8 + %14 = load i32, ptr %i, align 4 + %add14 = add nsw i32 %14, 2 + %idxprom15 = sext i32 %add14 to i64 + %arrayidx16 = getelementptr inbounds i16, ptr %13, i64 %idxprom15 + %15 = load i16, ptr %arrayidx16, align 2 + %conv17 = sext i16 %15 to i32 + %16 = load ptr, ptr %x.addr, align 8 + %17 = load i32, ptr %i, align 4 + %add18 = add nsw i32 %17, 2 + %idxprom19 = sext i32 %add18 to i64 + %arrayidx20 = getelementptr inbounds i16, ptr %16, i64 %idxprom19 + %18 = load i16, ptr %arrayidx20, align 2 + %conv21 = sext i16 %18 to i32 + %add22 = add nsw i32 %conv21, %conv17 + %conv23 = trunc i32 %add22 to i16 + store i16 %conv23, ptr %arrayidx20, align 2 + %19 = load ptr, ptr %y.addr, align 8 + %20 = load i32, ptr %i, align 4 + %add24 = add nsw i32 %20, 3 + %idxprom25 = sext i32 %add24 to i64 + %arrayidx26 = getelementptr inbounds i16, ptr %19, i64 %idxprom25 + %21 = load i16, ptr %arrayidx26, align 2 + %conv27 = sext i16 %21 to i32 + %22 = load ptr, ptr %x.addr, align 8 + %23 = load i32, ptr %i, align 4 + %add28 = add nsw i32 %23, 3 + %idxprom29 = sext i32 %add28 to i64 + %arrayidx30 = getelementptr inbounds i16, ptr %22, i64 %idxprom29 + %24 = load i16, ptr %arrayidx30, align 2 + %conv31 = sext i16 %24 to i32 + %sub32 = sub nsw i32 %conv31, %conv27 + %conv33 = trunc i32 %sub32 to i16 + store i16 %conv33, ptr %arrayidx30, align 2 + br label %for.inc + +for.inc: + %25 = load i32, ptr %i, align 4 + %add34 = add nsw i32 %25, 4 + store i32 %add34, ptr %i, align 4 + br label %for.cond + +for.end: + ret void +} + +; for(int i =0; i < 1024; i+=4) { +; x[i] += y[i]; +; x[i+1] += y[i+1]; +; x[i+2] -= y[i+2]; +; x[i+3] -= y[i+3]; +; } +define void @add2sub2(ptr noalias noundef %x, ptr noundef %y, i32 noundef %n) { +; CHECK-LABEL: @add2sub2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 -6 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i16, ptr [[Y:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <32 x i16>, ptr [[TMP0]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC24:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 +; CHECK-NEXT: [[TMP2:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP6]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP9:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i16> [[TMP9]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP8]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP5]], <16 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> [[TMP10]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP11]], <16 x i16> [[TMP12]], <32 x i32> +; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP13]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %x.addr = alloca ptr, align 8 + %y.addr = alloca ptr, align 8 + %n.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %x, ptr %x.addr, align 8 + store ptr %y, ptr %y.addr, align 8 + store i32 %n, ptr %n.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %1 = load ptr, ptr %y.addr, align 8 + %2 = load i32, ptr %i, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds i16, ptr %1, i64 %idxprom + %3 = load i16, ptr %arrayidx, align 2 + %conv = sext i16 %3 to i32 + %4 = load ptr, ptr %x.addr, align 8 + %5 = load i32, ptr %i, align 4 + %idxprom1 = sext i32 %5 to i64 + %arrayidx2 = getelementptr inbounds i16, ptr %4, i64 %idxprom1 + %6 = load i16, ptr %arrayidx2, align 2 + %conv3 = sext i16 %6 to i32 + %add = add nsw i32 %conv3, %conv + %conv4 = trunc i32 %add to i16 + store i16 %conv4, ptr %arrayidx2, align 2 + %7 = load ptr, ptr %y.addr, align 8 + %8 = load i32, ptr %i, align 4 + %add5 = add nsw i32 %8, 1 + %idxprom6 = sext i32 %add5 to i64 + %arrayidx7 = getelementptr inbounds i16, ptr %7, i64 %idxprom6 + %9 = load i16, ptr %arrayidx7, align 2 + %conv8 = sext i16 %9 to i32 + %10 = load ptr, ptr %x.addr, align 8 + %11 = load i32, ptr %i, align 4 + %add9 = add nsw i32 %11, 1 + %idxprom10 = sext i32 %add9 to i64 + %arrayidx11 = getelementptr inbounds i16, ptr %10, i64 %idxprom10 + %12 = load i16, ptr %arrayidx11, align 2 + %conv12 = sext i16 %12 to i32 + %add13 = add nsw i32 %conv12, %conv8 + %conv14 = trunc i32 %add13 to i16 + store i16 %conv14, ptr %arrayidx11, align 2 + %13 = load ptr, ptr %y.addr, align 8 + %14 = load i32, ptr %i, align 4 + %add15 = add nsw i32 %14, 2 + %idxprom16 = sext i32 %add15 to i64 + %arrayidx17 = getelementptr inbounds i16, ptr %13, i64 %idxprom16 + %15 = load i16, ptr %arrayidx17, align 2 + %conv18 = sext i16 %15 to i32 + %16 = load ptr, ptr %x.addr, align 8 + %17 = load i32, ptr %i, align 4 + %add19 = add nsw i32 %17, 2 + %idxprom20 = sext i32 %add19 to i64 + %arrayidx21 = getelementptr inbounds i16, ptr %16, i64 %idxprom20 + %18 = load i16, ptr %arrayidx21, align 2 + %conv22 = sext i16 %18 to i32 + %sub = sub nsw i32 %conv22, %conv18 + %conv23 = trunc i32 %sub to i16 + store i16 %conv23, ptr %arrayidx21, align 2 + %19 = load ptr, ptr %y.addr, align 8 + %20 = load i32, ptr %i, align 4 + %add24 = add nsw i32 %20, 3 + %idxprom25 = sext i32 %add24 to i64 + %arrayidx26 = getelementptr inbounds i16, ptr %19, i64 %idxprom25 + %21 = load i16, ptr %arrayidx26, align 2 + %conv27 = sext i16 %21 to i32 + %22 = load ptr, ptr %x.addr, align 8 + %23 = load i32, ptr %i, align 4 + %add28 = add nsw i32 %23, 3 + %idxprom29 = sext i32 %add28 to i64 + %arrayidx30 = getelementptr inbounds i16, ptr %22, i64 %idxprom29 + %24 = load i16, ptr %arrayidx30, align 2 + %conv31 = sext i16 %24 to i32 + %sub32 = sub nsw i32 %conv31, %conv27 + %conv33 = trunc i32 %sub32 to i16 + store i16 %conv33, ptr %arrayidx30, align 2 + br label %for.inc + +for.inc: + %25 = load i32, ptr %i, align 4 + %add34 = add nsw i32 %25, 4 + store i32 %add34, ptr %i, align 4 + br label %for.cond + +for.end: + ret void +} + +; for(int i =0; i < 1024; i+=4) { +; x[i] += y[i] * z[i]; +; x[i+1] += y[i+1] * z[i+1]; +; x[i+2] += y[i+2] * z[i+2]; +; x[i+3] += y[i+3] * z[i+3]; +; } +define void @addmul(ptr noalias noundef %x, ptr noundef %y, ptr noundef %z, i32 noundef %n) { +; CHECK-LABEL: @addmul( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 -6 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i16, ptr [[Y:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <32 x i16>, ptr [[TMP0]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[Z:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC31:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 +; CHECK-NEXT: [[TMP2:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC36:%.*]] = load <32 x i16>, ptr [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[TMP2]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP7:%.*]] = add <32 x i16> [[TMP6]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP7]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = add <32 x i16> [[TMP9]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <32 x i16> [[TMP10]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP13:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP14:%.*]] = add <32 x i16> [[TMP13]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <32 x i16> [[TMP14]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP12]] +; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[TMP8]], <16 x i32> +; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <8 x i16> [[TMP11]], <8 x i16> [[TMP15]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP16]], <16 x i16> [[TMP17]], <32 x i32> +; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP18]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %x.addr = alloca ptr, align 8 + %y.addr = alloca ptr, align 8 + %z.addr = alloca ptr, align 8 + %n.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %x, ptr %x.addr, align 8 + store ptr %y, ptr %y.addr, align 8 + store ptr %z, ptr %z.addr, align 8 + store i32 %n, ptr %n.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %1 = load ptr, ptr %y.addr, align 8 + %2 = load i32, ptr %i, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds i16, ptr %1, i64 %idxprom + %3 = load i16, ptr %arrayidx, align 2 + %conv = sext i16 %3 to i32 + %4 = load ptr, ptr %z.addr, align 8 + %5 = load i32, ptr %i, align 4 + %idxprom1 = sext i32 %5 to i64 + %arrayidx2 = getelementptr inbounds i16, ptr %4, i64 %idxprom1 + %6 = load i16, ptr %arrayidx2, align 2 + %conv3 = sext i16 %6 to i32 + %mul = mul nsw i32 %conv, %conv3 + %7 = load ptr, ptr %x.addr, align 8 + %8 = load i32, ptr %i, align 4 + %idxprom4 = sext i32 %8 to i64 + %arrayidx5 = getelementptr inbounds i16, ptr %7, i64 %idxprom4 + %9 = load i16, ptr %arrayidx5, align 2 + %conv6 = sext i16 %9 to i32 + %add = add nsw i32 %conv6, %mul + %conv7 = trunc i32 %add to i16 + store i16 %conv7, ptr %arrayidx5, align 2 + %10 = load ptr, ptr %y.addr, align 8 + %11 = load i32, ptr %i, align 4 + %add8 = add nsw i32 %11, 1 + %idxprom9 = sext i32 %add8 to i64 + %arrayidx10 = getelementptr inbounds i16, ptr %10, i64 %idxprom9 + %12 = load i16, ptr %arrayidx10, align 2 + %conv11 = sext i16 %12 to i32 + %13 = load ptr, ptr %z.addr, align 8 + %14 = load i32, ptr %i, align 4 + %add12 = add nsw i32 %14, 1 + %idxprom13 = sext i32 %add12 to i64 + %arrayidx14 = getelementptr inbounds i16, ptr %13, i64 %idxprom13 + %15 = load i16, ptr %arrayidx14, align 2 + %conv15 = sext i16 %15 to i32 + %mul16 = mul nsw i32 %conv11, %conv15 + %16 = load ptr, ptr %x.addr, align 8 + %17 = load i32, ptr %i, align 4 + %add17 = add nsw i32 %17, 1 + %idxprom18 = sext i32 %add17 to i64 + %arrayidx19 = getelementptr inbounds i16, ptr %16, i64 %idxprom18 + %18 = load i16, ptr %arrayidx19, align 2 + %conv20 = sext i16 %18 to i32 + %add21 = add nsw i32 %conv20, %mul16 + %conv22 = trunc i32 %add21 to i16 + store i16 %conv22, ptr %arrayidx19, align 2 + %19 = load ptr, ptr %y.addr, align 8 + %20 = load i32, ptr %i, align 4 + %add23 = add nsw i32 %20, 2 + %idxprom24 = sext i32 %add23 to i64 + %arrayidx25 = getelementptr inbounds i16, ptr %19, i64 %idxprom24 + %21 = load i16, ptr %arrayidx25, align 2 + %conv26 = sext i16 %21 to i32 + %22 = load ptr, ptr %z.addr, align 8 + %23 = load i32, ptr %i, align 4 + %add27 = add nsw i32 %23, 2 + %idxprom28 = sext i32 %add27 to i64 + %arrayidx29 = getelementptr inbounds i16, ptr %22, i64 %idxprom28 + %24 = load i16, ptr %arrayidx29, align 2 + %conv30 = sext i16 %24 to i32 + %mul31 = mul nsw i32 %conv26, %conv30 + %25 = load ptr, ptr %x.addr, align 8 + %26 = load i32, ptr %i, align 4 + %add32 = add nsw i32 %26, 2 + %idxprom33 = sext i32 %add32 to i64 + %arrayidx34 = getelementptr inbounds i16, ptr %25, i64 %idxprom33 + %27 = load i16, ptr %arrayidx34, align 2 + %conv35 = sext i16 %27 to i32 + %add36 = add nsw i32 %conv35, %mul31 + %conv37 = trunc i32 %add36 to i16 + store i16 %conv37, ptr %arrayidx34, align 2 + %28 = load ptr, ptr %y.addr, align 8 + %29 = load i32, ptr %i, align 4 + %add38 = add nsw i32 %29, 3 + %idxprom39 = sext i32 %add38 to i64 + %arrayidx40 = getelementptr inbounds i16, ptr %28, i64 %idxprom39 + %30 = load i16, ptr %arrayidx40, align 2 + %conv41 = sext i16 %30 to i32 + %31 = load ptr, ptr %z.addr, align 8 + %32 = load i32, ptr %i, align 4 + %add42 = add nsw i32 %32, 3 + %idxprom43 = sext i32 %add42 to i64 + %arrayidx44 = getelementptr inbounds i16, ptr %31, i64 %idxprom43 + %33 = load i16, ptr %arrayidx44, align 2 + %conv45 = sext i16 %33 to i32 + %mul46 = mul nsw i32 %conv41, %conv45 + %34 = load ptr, ptr %x.addr, align 8 + %35 = load i32, ptr %i, align 4 + %add47 = add nsw i32 %35, 3 + %idxprom48 = sext i32 %add47 to i64 + %arrayidx49 = getelementptr inbounds i16, ptr %34, i64 %idxprom48 + %36 = load i16, ptr %arrayidx49, align 2 + %conv50 = sext i16 %36 to i32 + %add51 = add nsw i32 %conv50, %mul46 + %conv52 = trunc i32 %add51 to i16 + store i16 %conv52, ptr %arrayidx49, align 2 + br label %for.inc + +for.inc: + %37 = load i32, ptr %i, align 4 + %add53 = add nsw i32 %37, 4 + store i32 %add53, ptr %i, align 4 + br label %for.cond + +for.end: + ret void +} + +; for(int i =0; i < 1024; i+=4) { +; x[i] += y[i] * z[i]; +; x[i+1] -= y[i+1] * z[i+1]; +; x[i+2] += y[i+2] * z[i+2]; +; x[i+3] -= y[i+3] * z[i+3]; +; } +define void @addsubsmul(ptr noalias noundef %x, ptr noundef %y, ptr noundef %z, i32 noundef %n) { +; CHECK-LABEL: @addsubsmul( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 -6 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i16, ptr [[Y:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <32 x i16>, ptr [[TMP0]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[Z:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC31:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 +; CHECK-NEXT: [[TMP2:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC36:%.*]] = load <32 x i16>, ptr [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[TMP2]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP7:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP7]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = add <32 x i16> [[TMP9]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <32 x i16> [[TMP10]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP13:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP14:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP13]] +; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <32 x i16> [[TMP14]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP12]] +; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[TMP8]], <16 x i32> +; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <8 x i16> [[TMP11]], <8 x i16> [[TMP15]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP16]], <16 x i16> [[TMP17]], <32 x i32> +; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP18]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %x.addr = alloca ptr, align 8 + %y.addr = alloca ptr, align 8 + %z.addr = alloca ptr, align 8 + %n.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %x, ptr %x.addr, align 8 + store ptr %y, ptr %y.addr, align 8 + store ptr %z, ptr %z.addr, align 8 + store i32 %n, ptr %n.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %1 = load ptr, ptr %y.addr, align 8 + %2 = load i32, ptr %i, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds i16, ptr %1, i64 %idxprom + %3 = load i16, ptr %arrayidx, align 2 + %conv = sext i16 %3 to i32 + %4 = load ptr, ptr %z.addr, align 8 + %5 = load i32, ptr %i, align 4 + %idxprom1 = sext i32 %5 to i64 + %arrayidx2 = getelementptr inbounds i16, ptr %4, i64 %idxprom1 + %6 = load i16, ptr %arrayidx2, align 2 + %conv3 = sext i16 %6 to i32 + %mul = mul nsw i32 %conv, %conv3 + %7 = load ptr, ptr %x.addr, align 8 + %8 = load i32, ptr %i, align 4 + %idxprom4 = sext i32 %8 to i64 + %arrayidx5 = getelementptr inbounds i16, ptr %7, i64 %idxprom4 + %9 = load i16, ptr %arrayidx5, align 2 + %conv6 = sext i16 %9 to i32 + %add = add nsw i32 %conv6, %mul + %conv7 = trunc i32 %add to i16 + store i16 %conv7, ptr %arrayidx5, align 2 + %10 = load ptr, ptr %y.addr, align 8 + %11 = load i32, ptr %i, align 4 + %add8 = add nsw i32 %11, 1 + %idxprom9 = sext i32 %add8 to i64 + %arrayidx10 = getelementptr inbounds i16, ptr %10, i64 %idxprom9 + %12 = load i16, ptr %arrayidx10, align 2 + %conv11 = sext i16 %12 to i32 + %13 = load ptr, ptr %z.addr, align 8 + %14 = load i32, ptr %i, align 4 + %add12 = add nsw i32 %14, 1 + %idxprom13 = sext i32 %add12 to i64 + %arrayidx14 = getelementptr inbounds i16, ptr %13, i64 %idxprom13 + %15 = load i16, ptr %arrayidx14, align 2 + %conv15 = sext i16 %15 to i32 + %mul16 = mul nsw i32 %conv11, %conv15 + %16 = load ptr, ptr %x.addr, align 8 + %17 = load i32, ptr %i, align 4 + %add17 = add nsw i32 %17, 1 + %idxprom18 = sext i32 %add17 to i64 + %arrayidx19 = getelementptr inbounds i16, ptr %16, i64 %idxprom18 + %18 = load i16, ptr %arrayidx19, align 2 + %conv20 = sext i16 %18 to i32 + %sub = sub nsw i32 %conv20, %mul16 + %conv21 = trunc i32 %sub to i16 + store i16 %conv21, ptr %arrayidx19, align 2 + %19 = load ptr, ptr %y.addr, align 8 + %20 = load i32, ptr %i, align 4 + %add22 = add nsw i32 %20, 2 + %idxprom23 = sext i32 %add22 to i64 + %arrayidx24 = getelementptr inbounds i16, ptr %19, i64 %idxprom23 + %21 = load i16, ptr %arrayidx24, align 2 + %conv25 = sext i16 %21 to i32 + %22 = load ptr, ptr %z.addr, align 8 + %23 = load i32, ptr %i, align 4 + %add26 = add nsw i32 %23, 2 + %idxprom27 = sext i32 %add26 to i64 + %arrayidx28 = getelementptr inbounds i16, ptr %22, i64 %idxprom27 + %24 = load i16, ptr %arrayidx28, align 2 + %conv29 = sext i16 %24 to i32 + %mul30 = mul nsw i32 %conv25, %conv29 + %25 = load ptr, ptr %x.addr, align 8 + %26 = load i32, ptr %i, align 4 + %add31 = add nsw i32 %26, 2 + %idxprom32 = sext i32 %add31 to i64 + %arrayidx33 = getelementptr inbounds i16, ptr %25, i64 %idxprom32 + %27 = load i16, ptr %arrayidx33, align 2 + %conv34 = sext i16 %27 to i32 + %add35 = add nsw i32 %conv34, %mul30 + %conv36 = trunc i32 %add35 to i16 + store i16 %conv36, ptr %arrayidx33, align 2 + %28 = load ptr, ptr %y.addr, align 8 + %29 = load i32, ptr %i, align 4 + %add37 = add nsw i32 %29, 3 + %idxprom38 = sext i32 %add37 to i64 + %arrayidx39 = getelementptr inbounds i16, ptr %28, i64 %idxprom38 + %30 = load i16, ptr %arrayidx39, align 2 + %conv40 = sext i16 %30 to i32 + %31 = load ptr, ptr %z.addr, align 8 + %32 = load i32, ptr %i, align 4 + %add41 = add nsw i32 %32, 3 + %idxprom42 = sext i32 %add41 to i64 + %arrayidx43 = getelementptr inbounds i16, ptr %31, i64 %idxprom42 + %33 = load i16, ptr %arrayidx43, align 2 + %conv44 = sext i16 %33 to i32 + %mul45 = mul nsw i32 %conv40, %conv44 + %34 = load ptr, ptr %x.addr, align 8 + %35 = load i32, ptr %i, align 4 + %add46 = add nsw i32 %35, 3 + %idxprom47 = sext i32 %add46 to i64 + %arrayidx48 = getelementptr inbounds i16, ptr %34, i64 %idxprom47 + %36 = load i16, ptr %arrayidx48, align 2 + %conv49 = sext i16 %36 to i32 + %sub50 = sub nsw i32 %conv49, %mul45 + %conv51 = trunc i32 %sub50 to i16 + store i16 %conv51, ptr %arrayidx48, align 2 + br label %for.inc + +for.inc: + %37 = load i32, ptr %i, align 4 + %add52 = add nsw i32 %37, 4 + store i32 %add52, ptr %i, align 4 + br label %for.cond + +for.end: + ret void +} + +; for(int i =0; i < 1024; i+=4) { +; x[i] += y[i] * z[i]; +; x[i+1] += y[i+1] * z[i+1]; +; x[i+2] -= y[i+2] * z[i+2]; +; x[i+3] -= y[i+3] * z[i+3]; +; } +define void @add2sub2mul(ptr noalias noundef %x, ptr noundef %y, ptr noundef %z, i32 noundef %n) { +; CHECK-LABEL: @add2sub2mul( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 -6 +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i16, ptr [[Y:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <32 x i16>, ptr [[TMP0]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[Z:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC31:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 +; CHECK-NEXT: [[TMP2:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_VEC36:%.*]] = load <32 x i16>, ptr [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[TMP2]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP7:%.*]] = add <32 x i16> [[TMP6]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP7]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP9]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <32 x i16> [[TMP10]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP13:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP14:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP13]] +; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <32 x i16> [[TMP14]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP12]] +; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[TMP8]], <16 x i32> +; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <8 x i16> [[TMP11]], <8 x i16> [[TMP15]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP16]], <16 x i16> [[TMP17]], <32 x i32> +; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP18]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %x.addr = alloca ptr, align 8 + %y.addr = alloca ptr, align 8 + %z.addr = alloca ptr, align 8 + %n.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %x, ptr %x.addr, align 8 + store ptr %y, ptr %y.addr, align 8 + store ptr %z, ptr %z.addr, align 8 + store i32 %n, ptr %n.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: + %0 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %1 = load ptr, ptr %y.addr, align 8 + %2 = load i32, ptr %i, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds i16, ptr %1, i64 %idxprom + %3 = load i16, ptr %arrayidx, align 2 + %conv = sext i16 %3 to i32 + %4 = load ptr, ptr %z.addr, align 8 + %5 = load i32, ptr %i, align 4 + %idxprom1 = sext i32 %5 to i64 + %arrayidx2 = getelementptr inbounds i16, ptr %4, i64 %idxprom1 + %6 = load i16, ptr %arrayidx2, align 2 + %conv3 = sext i16 %6 to i32 + %mul = mul nsw i32 %conv, %conv3 + %7 = load ptr, ptr %x.addr, align 8 + %8 = load i32, ptr %i, align 4 + %idxprom4 = sext i32 %8 to i64 + %arrayidx5 = getelementptr inbounds i16, ptr %7, i64 %idxprom4 + %9 = load i16, ptr %arrayidx5, align 2 + %conv6 = sext i16 %9 to i32 + %add = add nsw i32 %conv6, %mul + %conv7 = trunc i32 %add to i16 + store i16 %conv7, ptr %arrayidx5, align 2 + %10 = load ptr, ptr %y.addr, align 8 + %11 = load i32, ptr %i, align 4 + %add8 = add nsw i32 %11, 1 + %idxprom9 = sext i32 %add8 to i64 + %arrayidx10 = getelementptr inbounds i16, ptr %10, i64 %idxprom9 + %12 = load i16, ptr %arrayidx10, align 2 + %conv11 = sext i16 %12 to i32 + %13 = load ptr, ptr %z.addr, align 8 + %14 = load i32, ptr %i, align 4 + %add12 = add nsw i32 %14, 1 + %idxprom13 = sext i32 %add12 to i64 + %arrayidx14 = getelementptr inbounds i16, ptr %13, i64 %idxprom13 + %15 = load i16, ptr %arrayidx14, align 2 + %conv15 = sext i16 %15 to i32 + %mul16 = mul nsw i32 %conv11, %conv15 + %16 = load ptr, ptr %x.addr, align 8 + %17 = load i32, ptr %i, align 4 + %add17 = add nsw i32 %17, 1 + %idxprom18 = sext i32 %add17 to i64 + %arrayidx19 = getelementptr inbounds i16, ptr %16, i64 %idxprom18 + %18 = load i16, ptr %arrayidx19, align 2 + %conv20 = sext i16 %18 to i32 + %add21 = add nsw i32 %conv20, %mul16 + %conv22 = trunc i32 %add21 to i16 + store i16 %conv22, ptr %arrayidx19, align 2 + %19 = load ptr, ptr %y.addr, align 8 + %20 = load i32, ptr %i, align 4 + %add23 = add nsw i32 %20, 2 + %idxprom24 = sext i32 %add23 to i64 + %arrayidx25 = getelementptr inbounds i16, ptr %19, i64 %idxprom24 + %21 = load i16, ptr %arrayidx25, align 2 + %conv26 = sext i16 %21 to i32 + %22 = load ptr, ptr %z.addr, align 8 + %23 = load i32, ptr %i, align 4 + %add27 = add nsw i32 %23, 2 + %idxprom28 = sext i32 %add27 to i64 + %arrayidx29 = getelementptr inbounds i16, ptr %22, i64 %idxprom28 + %24 = load i16, ptr %arrayidx29, align 2 + %conv30 = sext i16 %24 to i32 + %mul31 = mul nsw i32 %conv26, %conv30 + %25 = load ptr, ptr %x.addr, align 8 + %26 = load i32, ptr %i, align 4 + %add32 = add nsw i32 %26, 2 + %idxprom33 = sext i32 %add32 to i64 + %arrayidx34 = getelementptr inbounds i16, ptr %25, i64 %idxprom33 + %27 = load i16, ptr %arrayidx34, align 2 + %conv35 = sext i16 %27 to i32 + %sub = sub nsw i32 %conv35, %mul31 + %conv36 = trunc i32 %sub to i16 + store i16 %conv36, ptr %arrayidx34, align 2 + %28 = load ptr, ptr %y.addr, align 8 + %29 = load i32, ptr %i, align 4 + %add37 = add nsw i32 %29, 3 + %idxprom38 = sext i32 %add37 to i64 + %arrayidx39 = getelementptr inbounds i16, ptr %28, i64 %idxprom38 + %30 = load i16, ptr %arrayidx39, align 2 + %conv40 = sext i16 %30 to i32 + %31 = load ptr, ptr %z.addr, align 8 + %32 = load i32, ptr %i, align 4 + %add41 = add nsw i32 %32, 3 + %idxprom42 = sext i32 %add41 to i64 + %arrayidx43 = getelementptr inbounds i16, ptr %31, i64 %idxprom42 + %33 = load i16, ptr %arrayidx43, align 2 + %conv44 = sext i16 %33 to i32 + %mul45 = mul nsw i32 %conv40, %conv44 + %34 = load ptr, ptr %x.addr, align 8 + %35 = load i32, ptr %i, align 4 + %add46 = add nsw i32 %35, 3 + %idxprom47 = sext i32 %add46 to i64 + %arrayidx48 = getelementptr inbounds i16, ptr %34, i64 %idxprom47 + %36 = load i16, ptr %arrayidx48, align 2 + %conv49 = sext i16 %36 to i32 + %sub50 = sub nsw i32 %conv49, %mul45 + %conv51 = trunc i32 %sub50 to i16 + store i16 %conv51, ptr %arrayidx48, align 2 + br label %for.inc + +for.inc: + %37 = load i32, ptr %i, align 4 + %add52 = add nsw i32 %37, 4 + store i32 %add52, ptr %i, align 4 + br label %for.cond + +for.end: + ret void +} -- GitLab From a8105026ff548412967bc68ffb57f4fb6aecb652 Mon Sep 17 00:00:00 2001 From: David Green Date: Sat, 20 Apr 2024 16:40:08 +0100 Subject: [PATCH 086/357] [LV] Fix warning about Mask being set twice. NFC --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index adae7caf5917..33c4decd58a6 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -9382,9 +9382,9 @@ void VPWidenLoadEVLRecipe::execute(VPTransformState &State) { CallInst *NewLI; Value *EVL = State.get(getEVL(), VPIteration(0, 0)); Value *Addr = State.get(getAddr(), 0, !CreateGather); - Value *Mask = - getMask() ? State.get(getMask(), 0) - : Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue()); + Value *Mask = getMask() + ? State.get(getMask(), 0) + : Builder.CreateVectorSplat(State.VF, Builder.getTrue()); if (CreateGather) { NewLI = Builder.CreateIntrinsic(DataTy, Intrinsic::vp_gather, {Addr, Mask, EVL}, @@ -9460,9 +9460,9 @@ void VPWidenStoreEVLRecipe::execute(VPTransformState &State) { Value *StoredVal = State.get(StoredValue, 0); Value *EVL = State.get(getEVL(), VPIteration(0, 0)); // FIXME: Support reverse store after vp_reverse is added. - Value *Mask = - getMask() ? State.get(getMask(), 0) - : Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue()); + Value *Mask = getMask() + ? State.get(getMask(), 0) + : Builder.CreateVectorSplat(State.VF, Builder.getTrue()); Value *Addr = State.get(getAddr(), 0, !CreateScatter); if (CreateScatter) { NewSI = Builder.CreateIntrinsic(Type::getVoidTy(EVL->getContext()), -- GitLab From efe0a2eddb5e71034d426d8c9bd7510e544fb191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Degioanni?= Date: Sat, 20 Apr 2024 19:23:25 +0200 Subject: [PATCH 087/357] [nfc][github] subscribe myself to MLIR Mem2Reg PRs --- .github/CODEOWNERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 37aea5f6657f..45da8af51bb9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -119,6 +119,10 @@ clang/test/AST/Interp/ @tbaederr /mlir/test/python/ @ftynse @makslevental @stellaraccident /mlir/python/ @ftynse @makslevental @stellaraccident +# MLIR Mem2Reg/SROA +/mlir/**/Transforms/Mem2Reg.* @moxinilian +/mlir/**/Transforms/SROA.* @moxinilian + # BOLT /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci -- GitLab From 7f0bbbb19b4f13c2efb400db300817aa7ed589cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 19 Apr 2024 17:31:28 +0200 Subject: [PATCH 088/357] [clang][Interp] Change array index types in OffsetHelper This is closer to that the current interpreter does. It also fixes diagnostics in a case I was looking into. Unfortunately, this is not possible to test right now since it requires a large array and we don't implement array fillers yet. --- clang/lib/AST/Interp/Interp.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index dd0bacd73acb..cebedf59e059 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1548,17 +1548,16 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, if (!CheckArray(S, OpPC, Ptr)) return false; - // Get a version of the index comparable to the type. - T Index = T::from(Ptr.getIndex(), Offset.bitWidth()); - // Compute the largest index into the array. - T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth()); + uint64_t Index = Ptr.getIndex(); + uint64_t MaxIndex = static_cast(Ptr.getNumElems()); bool Invalid = false; // Helper to report an invalid offset, computed as APSInt. auto DiagInvalidOffset = [&]() -> void { const unsigned Bits = Offset.bitWidth(); - APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false); - APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false); + APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), /*IsUnsigend=*/false); + APSInt APIndex(APInt(Bits + 2, Index, /*IsSigned=*/true), + /*IsUnsigned=*/false); APSInt NewIndex = (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index) @@ -1569,22 +1568,24 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, }; if (Ptr.isBlockPointer()) { - T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth()); + uint64_t IOffset = static_cast(Offset); + uint64_t MaxOffset = MaxIndex - Index; + if constexpr (Op == ArithOp::Add) { // If the new offset would be negative, bail out. - if (Offset.isNegative() && (Offset.isMin() || -Offset > Index)) + if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index)) DiagInvalidOffset(); // If the new offset would be out of bounds, bail out. - if (Offset.isPositive() && Offset > MaxOffset) + if (Offset.isPositive() && IOffset > MaxOffset) DiagInvalidOffset(); } else { // If the new offset would be negative, bail out. - if (Offset.isPositive() && Index < Offset) + if (Offset.isPositive() && Index < IOffset) DiagInvalidOffset(); // If the new offset would be out of bounds, bail out. - if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset)) + if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset)) DiagInvalidOffset(); } } @@ -1601,7 +1602,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, else Result = WideIndex - WideOffset; - S.Stk.push(Ptr.atIndex(static_cast(Result))); + S.Stk.push(Ptr.atIndex(static_cast(Result))); return true; } -- GitLab From 1faf3148fdef34ce0d556ec6a4049e06cbde71b3 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Sat, 20 Apr 2024 20:54:55 +0300 Subject: [PATCH 089/357] [clang-repl] Keep the first llvm::Module empty to avoid invalid memory access. (#89031) Clang's CodeGen is designed to work with a single llvm::Module. In many cases for convenience various CodeGen parts have a reference to the llvm::Module (TheModule or Module) which does not change when a new module is pushed. However, the execution engine wants to take ownership of the module which does not map well to CodeGen's design. To work this around we clone the module and pass it down. With some effort it is possible to teach CodeGen to ask the CodeGenModule for its current module and that would have an overall positive impact on CodeGen improving the encapsulation of various parts but that's not resilient to future regression. This patch takes a more conservative approach and keeps the first llvm::Module empty intentionally and does not pass it to the Jit. That's also not bullet proof because we have to guarantee that CodeGen does not write on the blueprint. However, we have inserted some assertions to catch accidental additions to that canary module. This change will fixes a long-standing invalid memory access reported by valgrind when we enable the TBAA optimization passes. It also unblock progress on https://github.com/llvm/llvm-project/pull/84758. --- clang/lib/Interpreter/IncrementalParser.cpp | 25 ++++++++++++++++----- clang/lib/Interpreter/IncrementalParser.h | 5 +++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5eec2a2fd6d1..c87972719b66 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -209,6 +209,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, if (Err) return; CI->ExecuteAction(*Act); + + if (getCodeGen()) + CachedInCodeGenModule = std::move(GenModule()); + std::unique_ptr IncrConsumer = std::make_unique(Interp, CI->takeASTConsumer()); CI->setASTConsumer(std::move(IncrConsumer)); @@ -224,11 +228,8 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, return; // PTU.takeError(); } - if (CodeGenerator *CG = getCodeGen()) { - std::unique_ptr M(CG->ReleaseModule()); - CG->StartModule("incr_module_" + std::to_string(PTUs.size()), - M->getContext()); - PTU->TheModule = std::move(M); + if (getCodeGen()) { + PTU->TheModule = std::move(GenModule()); assert(PTU->TheModule && "Failed to create initial PTU"); } } @@ -364,6 +365,20 @@ IncrementalParser::Parse(llvm::StringRef input) { std::unique_ptr IncrementalParser::GenModule() { static unsigned ID = 0; if (CodeGenerator *CG = getCodeGen()) { + // Clang's CodeGen is designed to work with a single llvm::Module. In many + // cases for convenience various CodeGen parts have a reference to the + // llvm::Module (TheModule or Module) which does not change when a new + // module is pushed. However, the execution engine wants to take ownership + // of the module which does not map well to CodeGen's design. To work this + // around we created an empty module to make CodeGen happy. We should make + // sure it always stays empty. + assert((!CachedInCodeGenModule || + (CachedInCodeGenModule->empty() && + CachedInCodeGenModule->global_empty() && + CachedInCodeGenModule->alias_empty() && + CachedInCodeGenModule->ifunc_empty() && + CachedInCodeGenModule->named_metadata_empty())) && + "CodeGen wrote to a readonly module"); std::unique_ptr M(CG->ReleaseModule()); CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); return M; diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index e13b74c7f659..f63bce50acd3 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -24,6 +24,7 @@ #include namespace llvm { class LLVMContext; +class Module; } // namespace llvm namespace clang { @@ -57,6 +58,10 @@ protected: /// of code. std::list PTUs; + /// When CodeGen is created the first llvm::Module gets cached in many places + /// and we must keep it alive. + std::unique_ptr CachedInCodeGenModule; + IncrementalParser(); public: -- GitLab From 34dffc5e00b2428e3c824029891f3c8fbf411d2c Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sat, 20 Apr 2024 10:55:12 -0700 Subject: [PATCH 090/357] [memprof] Accept Schema in the constructor of RecordWriterTrait (NFC) (#89486) The comment being deleted in this patch is not correct. We already construct an instance of RecordWriterTrait with Version. This patch teaches the constructor of RecordWriterTrait to accept Schema. While I am at it, this patch makes Version a private variable. --- llvm/include/llvm/ProfileData/MemProf.h | 11 ++++++----- llvm/lib/ProfileData/InstrProfWriter.cpp | 3 +-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index faaec331c823..59ef59fd33a3 100644 --- a/llvm/include/llvm/ProfileData/MemProf.h +++ b/llvm/include/llvm/ProfileData/MemProf.h @@ -514,16 +514,17 @@ public: using hash_value_type = uint64_t; using offset_type = uint64_t; - // Pointer to the memprof schema to use for the generator. Unlike the reader - // we must use a default constructor with no params for the writer trait so we - // have a public member which must be initialized by the user. - MemProfSchema *Schema = nullptr; +private: + // Pointer to the memprof schema to use for the generator. + const MemProfSchema *Schema; // The MemProf version to use for the serialization. IndexedVersion Version; +public: // We do not support the default constructor, which does not set Version. RecordWriterTrait() = delete; - RecordWriterTrait(IndexedVersion V) : Version(V) {} + RecordWriterTrait(const MemProfSchema *Schema, IndexedVersion V) + : Schema(Schema), Version(V) {} static hash_value_type ComputeHash(key_type_ref K) { return K; } diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index 0bc5f5206dc2..4a6fc9d64b69 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -451,8 +451,7 @@ static uint64_t writeMemProfRecords( llvm::MapVector &MemProfRecordData, memprof::MemProfSchema *Schema, memprof::IndexedVersion Version) { - memprof::RecordWriterTrait RecordWriter(Version); - RecordWriter.Schema = Schema; + memprof::RecordWriterTrait RecordWriter(Schema, Version); OnDiskChainedHashTableGenerator RecordTableGenerator; for (auto &[GUID, Record] : MemProfRecordData) { -- GitLab From ca090452d64e229b539a66379a3be891c4e8f3d8 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sat, 20 Apr 2024 11:10:49 -0700 Subject: [PATCH 091/357] [Interpreter] Fix warnings This patch fixes: clang/lib/Interpreter/IncrementalParser.cpp:214:29: error: moving a temporary object prevents copy elision [-Werror,-Wpessimizing-move] clang/lib/Interpreter/IncrementalParser.cpp:232:22: error: moving a temporary object prevents copy elision [-Werror,-Wpessimizing-move] --- clang/lib/Interpreter/IncrementalParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index c87972719b66..b72005d58f83 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -211,7 +211,7 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, CI->ExecuteAction(*Act); if (getCodeGen()) - CachedInCodeGenModule = std::move(GenModule()); + CachedInCodeGenModule = GenModule(); std::unique_ptr IncrConsumer = std::make_unique(Interp, CI->takeASTConsumer()); @@ -229,7 +229,7 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, } if (getCodeGen()) { - PTU->TheModule = std::move(GenModule()); + PTU->TheModule = GenModule(); assert(PTU->TheModule && "Failed to create initial PTU"); } } -- GitLab From adc4f6233df734fbe3793118ecc89d3584e0c90f Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Sat, 20 Apr 2024 18:26:19 +0000 Subject: [PATCH 092/357] Revert "[clang-repl] Keep the first llvm::Module empty to avoid invalid memory access. (#89031)" This reverts commit ca090452d64e229b539a66379a3be891c4e8f3d8 and 1faf3148fdef34ce0d556ec6a4049e06cbde71b3 because it broke a darwin bot. --- clang/lib/Interpreter/IncrementalParser.cpp | 25 +++++---------------- clang/lib/Interpreter/IncrementalParser.h | 5 ----- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index b72005d58f83..5eec2a2fd6d1 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -209,10 +209,6 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, if (Err) return; CI->ExecuteAction(*Act); - - if (getCodeGen()) - CachedInCodeGenModule = GenModule(); - std::unique_ptr IncrConsumer = std::make_unique(Interp, CI->takeASTConsumer()); CI->setASTConsumer(std::move(IncrConsumer)); @@ -228,8 +224,11 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, return; // PTU.takeError(); } - if (getCodeGen()) { - PTU->TheModule = GenModule(); + if (CodeGenerator *CG = getCodeGen()) { + std::unique_ptr M(CG->ReleaseModule()); + CG->StartModule("incr_module_" + std::to_string(PTUs.size()), + M->getContext()); + PTU->TheModule = std::move(M); assert(PTU->TheModule && "Failed to create initial PTU"); } } @@ -365,20 +364,6 @@ IncrementalParser::Parse(llvm::StringRef input) { std::unique_ptr IncrementalParser::GenModule() { static unsigned ID = 0; if (CodeGenerator *CG = getCodeGen()) { - // Clang's CodeGen is designed to work with a single llvm::Module. In many - // cases for convenience various CodeGen parts have a reference to the - // llvm::Module (TheModule or Module) which does not change when a new - // module is pushed. However, the execution engine wants to take ownership - // of the module which does not map well to CodeGen's design. To work this - // around we created an empty module to make CodeGen happy. We should make - // sure it always stays empty. - assert((!CachedInCodeGenModule || - (CachedInCodeGenModule->empty() && - CachedInCodeGenModule->global_empty() && - CachedInCodeGenModule->alias_empty() && - CachedInCodeGenModule->ifunc_empty() && - CachedInCodeGenModule->named_metadata_empty())) && - "CodeGen wrote to a readonly module"); std::unique_ptr M(CG->ReleaseModule()); CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); return M; diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index f63bce50acd3..e13b74c7f659 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -24,7 +24,6 @@ #include namespace llvm { class LLVMContext; -class Module; } // namespace llvm namespace clang { @@ -58,10 +57,6 @@ protected: /// of code. std::list PTUs; - /// When CodeGen is created the first llvm::Module gets cached in many places - /// and we must keep it alive. - std::unique_ptr CachedInCodeGenModule; - IncrementalParser(); public: -- GitLab From a3f07d36cbc9e3a0d004609d140474c1d8a25bb6 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Sat, 20 Apr 2024 18:28:38 +0000 Subject: [PATCH 093/357] Reland "[clang-repl] Keep the first llvm::Module empty to avoid invalid memory access. (#89031)" Original commit message: " Clang's CodeGen is designed to work with a single llvm::Module. In many cases for convenience various CodeGen parts have a reference to the llvm::Module (TheModule or Module) which does not change when a new module is pushed. However, the execution engine wants to take ownership of the module which does not map well to CodeGen's design. To work this around we clone the module and pass it down. With some effort it is possible to teach CodeGen to ask the CodeGenModule for its current module and that would have an overall positive impact on CodeGen improving the encapsulation of various parts but that's not resilient to future regression. This patch takes a more conservative approach and keeps the first llvm::Module empty intentionally and does not pass it to the Jit. That's also not bullet proof because we have to guarantee that CodeGen does not write on the blueprint. However, we have inserted some assertions to catch accidental additions to that canary module. This change will fixes a long-standing invalid memory access reported by valgrind when we enable the TBAA optimization passes. It also unblock progress on https://github.com/llvm/llvm-project/pull/84758. " This patch reverts adc4f6233df734fbe3793118ecc89d3584e0c90f and removes the check of `named_metadata_empty` of the first llvm::Module because on darwin clang inserts some harmless metadata which we can ignore. --- clang/lib/Interpreter/IncrementalParser.cpp | 24 ++++++++++++++++----- clang/lib/Interpreter/IncrementalParser.h | 5 +++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5eec2a2fd6d1..ef90fe9e6f54 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -209,6 +209,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, if (Err) return; CI->ExecuteAction(*Act); + + if (getCodeGen()) + CachedInCodeGenModule = GenModule(); + std::unique_ptr IncrConsumer = std::make_unique(Interp, CI->takeASTConsumer()); CI->setASTConsumer(std::move(IncrConsumer)); @@ -224,11 +228,8 @@ IncrementalParser::IncrementalParser(Interpreter &Interp, return; // PTU.takeError(); } - if (CodeGenerator *CG = getCodeGen()) { - std::unique_ptr M(CG->ReleaseModule()); - CG->StartModule("incr_module_" + std::to_string(PTUs.size()), - M->getContext()); - PTU->TheModule = std::move(M); + if (getCodeGen()) { + PTU->TheModule = GenModule(); assert(PTU->TheModule && "Failed to create initial PTU"); } } @@ -364,6 +365,19 @@ IncrementalParser::Parse(llvm::StringRef input) { std::unique_ptr IncrementalParser::GenModule() { static unsigned ID = 0; if (CodeGenerator *CG = getCodeGen()) { + // Clang's CodeGen is designed to work with a single llvm::Module. In many + // cases for convenience various CodeGen parts have a reference to the + // llvm::Module (TheModule or Module) which does not change when a new + // module is pushed. However, the execution engine wants to take ownership + // of the module which does not map well to CodeGen's design. To work this + // around we created an empty module to make CodeGen happy. We should make + // sure it always stays empty. + assert((!CachedInCodeGenModule || + (CachedInCodeGenModule->empty() && + CachedInCodeGenModule->global_empty() && + CachedInCodeGenModule->alias_empty() && + CachedInCodeGenModule->ifunc_empty())) && + "CodeGen wrote to a readonly module"); std::unique_ptr M(CG->ReleaseModule()); CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); return M; diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index e13b74c7f659..f63bce50acd3 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -24,6 +24,7 @@ #include namespace llvm { class LLVMContext; +class Module; } // namespace llvm namespace clang { @@ -57,6 +58,10 @@ protected: /// of code. std::list PTUs; + /// When CodeGen is created the first llvm::Module gets cached in many places + /// and we must keep it alive. + std::unique_ptr CachedInCodeGenModule; + IncrementalParser(); public: -- GitLab From b6824c9d459da059e247a60c1ebd1aeb580dacc2 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Sat, 20 Apr 2024 14:39:03 -0700 Subject: [PATCH 094/357] Revert "Reland "[python] Bump Python minimum version to 3.8 (#78828)"" This reverts commit f2931182fc877e813974a5f53721f859bfb5b130. This was again causing buildbot failures. #83962 has been updated with the new failures, notifying the buildbot maintainers that they need to update their bots. --- llvm/CMakeLists.txt | 4 ++-- llvm/docs/GettingStarted.rst | 8 ++++---- llvm/docs/GettingStartedVS.rst | 2 +- llvm/docs/ReleaseNotes.rst | 5 ----- llvm/docs/TestingGuide.rst | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 505870154dbb..d511376e18ba 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -903,8 +903,8 @@ set(LLVM_PROFDATA_FILE "" CACHE FILEPATH "Profiling data file to use when compiling in order to improve runtime performance.") if(LLVM_INCLUDE_TESTS) - # All LLVM Python files should be compatible down to this minimum version. - set(LLVM_MINIMUM_PYTHON_VERSION 3.8) + # Lit test suite requires at least python 3.6 + set(LLVM_MINIMUM_PYTHON_VERSION 3.6) else() # FIXME: it is unknown if this is the actual minimum bound set(LLVM_MINIMUM_PYTHON_VERSION 3.0) diff --git a/llvm/docs/GettingStarted.rst b/llvm/docs/GettingStarted.rst index 0a1913dca8aa..7ecef78c405b 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -292,16 +292,16 @@ uses the package and provides other details. Package Version Notes =========================================================== ============ ========================================== `CMake `__ >=3.20.0 Makefile/workspace generator -`python `_ >=3.8 Automated test suite\ :sup:`1` +`python `_ >=3.6 Automated test suite\ :sup:`1` `zlib `_ >=1.2.3.4 Compression library\ :sup:`2` `GNU Make `_ 3.79, 3.79.1 Makefile/build processor\ :sup:`3` =========================================================== ============ ========================================== .. note:: - #. Only needed if you want to run the automated test suite in the - ``llvm/test`` directory, or if you plan to utilize any Python libraries, - utilities, or bindings. + #. Only needed if you want to run the automated test suite. Python 3.8.0 + or later is needed on Windows if a substitute (virtual) drive is used + to access LLVM source code due to ``MAX_PATH`` limitations. #. Optional, adds compression / uncompression capabilities to selected LLVM tools. #. Optional, you can use any other build tool supported by CMake. diff --git a/llvm/docs/GettingStartedVS.rst b/llvm/docs/GettingStartedVS.rst index 4b15272635fb..a1eb88dccc9e 100644 --- a/llvm/docs/GettingStartedVS.rst +++ b/llvm/docs/GettingStartedVS.rst @@ -55,7 +55,7 @@ Visual Studio 2019 so separate installation is not required. If you do install CMake separately, Visual Studio 2022 will require CMake Version 3.21 or later. If you would like to run the LLVM tests you will need `Python -`_. Version 3.8 and newer are known to work. You can +`_. Version 3.6 and newer are known to work. You can install Python with Visual Studio 2019, from the Microsoft store or from the `Python web site `_. We recommend the latter since it allows you to adjust installation options. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 33b61688f787..76ef6ceb9407 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -47,11 +47,6 @@ Non-comprehensive list of changes in this release Update on required toolchains to build LLVM ------------------------------------------- -* The minimum Python version has been raised from 3.6 to 3.8 across all of LLVM. - This enables the use of many new Python features, aligning more closely with - modern Python best practices, and improves CI maintainability - See `#78828 `_ for more info. - Changes to the LLVM IR ---------------------- diff --git a/llvm/docs/TestingGuide.rst b/llvm/docs/TestingGuide.rst index 3e3a722f1418..e32e4d1e535a 100644 --- a/llvm/docs/TestingGuide.rst +++ b/llvm/docs/TestingGuide.rst @@ -23,7 +23,7 @@ Requirements ============ In order to use the LLVM testing infrastructure, you will need all of the -software required to build LLVM, as well as `Python `_ 3.8 or +software required to build LLVM, as well as `Python `_ 3.6 or later. LLVM Testing Infrastructure Organization -- GitLab From 34acbb3801515f9f41cc2d790d26072eb004ac46 Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Sat, 20 Apr 2024 21:40:06 -0400 Subject: [PATCH 095/357] [X86] X86LowerTileCopy: Find dead register to use to prevent save-reload of tile register (#83628) --- llvm/lib/Target/X86/X86LowerTileCopy.cpp | 61 +++++++++++++------ .../CodeGen/X86/AMX/amx-lower-tile-copy.ll | 10 --- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/X86/X86LowerTileCopy.cpp b/llvm/lib/Target/X86/X86LowerTileCopy.cpp index e7afc49240e5..2ca21e69e591 100644 --- a/llvm/lib/Target/X86/X86LowerTileCopy.cpp +++ b/llvm/lib/Target/X86/X86LowerTileCopy.cpp @@ -20,6 +20,7 @@ #include "X86InstrBuilder.h" #include "X86InstrInfo.h" #include "X86Subtarget.h" +#include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -72,10 +73,16 @@ FunctionPass *llvm::createX86LowerTileCopyPass() { bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { const X86Subtarget &ST = MF.getSubtarget(); const X86InstrInfo *TII = ST.getInstrInfo(); + const TargetRegisterInfo *TRI = ST.getRegisterInfo(); + BitVector GR64Regs = + TRI->getAllocatableSet(MF, TRI->getRegClass(X86::GR64RegClassID)); bool Changed = false; for (MachineBasicBlock &MBB : MF) { - for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { + LiveRegUnits UsedRegs(*TRI); + UsedRegs.addLiveOuts(MBB); + for (MachineInstr &MI : llvm::make_early_inc_range(reverse(MBB))) { + UsedRegs.stepBackward(MI); if (!MI.isCopy()) continue; MachineOperand &DstMO = MI.getOperand(0); @@ -85,27 +92,41 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { if (!X86::TILERegClass.contains(DstReg, SrcReg)) continue; - const TargetRegisterInfo *TRI = ST.getRegisterInfo(); // Allocate stack slot for tile register unsigned Size = TRI->getSpillSize(X86::TILERegClass); Align Alignment = TRI->getSpillAlign(X86::TILERegClass); int TileSS = MF.getFrameInfo().CreateSpillStackObject(Size, Alignment); - // Allocate stack slot for stride register - Size = TRI->getSpillSize(X86::GR64RegClass); - Alignment = TRI->getSpillAlign(X86::GR64RegClass); - int StrideSS = MF.getFrameInfo().CreateSpillStackObject(Size, Alignment); - // TODO: Pick a killed regiter to avoid save/reload. There is problem - // to get live interval in this stage. - Register GR64Cand = X86::RAX; + int StrideSS = 0; + + // Pick a killed register to avoid a save/reload. + Register GR64Cand = X86::NoRegister; + for (auto RegT : GR64Regs.set_bits()) { + if (UsedRegs.available(RegT)) { + GR64Cand = RegT; + break; + } + } const DebugLoc &DL = MI.getDebugLoc(); - // mov %rax (%sp) - BuildMI(MBB, MI, DL, TII->get(X86::IMPLICIT_DEF), GR64Cand); - addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV64mr)), StrideSS) - .addReg(GR64Cand); - // mov 64 %rax - BuildMI(MBB, MI, DL, TII->get(X86::MOV64ri), GR64Cand).addImm(64); + if (GR64Cand) { + // mov 64 %reg + BuildMI(MBB, MI, DL, TII->get(X86::MOV64ri), GR64Cand).addImm(64); + } else { + // No available register? Save RAX and reload it after use. + + // Allocate stack slot for stride register + Size = TRI->getSpillSize(X86::GR64RegClass); + Alignment = TRI->getSpillAlign(X86::GR64RegClass); + StrideSS = MF.getFrameInfo().CreateSpillStackObject(Size, Alignment); + + // mov %reg (%sp) + addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV64mr)), + StrideSS) + .addReg(X86::RAX); + // mov 64 %reg + BuildMI(MBB, MI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(64); + } // tilestored %tmm, (%sp, %idx) #define GET_EGPR_IF_ENABLED(OPC) (ST.hasEGPR() ? OPC##_EVEX : OPC) unsigned Opc = GET_EGPR_IF_ENABLED(X86::TILESTORED); @@ -120,10 +141,12 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { #undef GET_EGPR_IF_ENABLED NewMI = addFrameReference(BuildMI(MBB, MI, DL, TII->get(Opc), DstReg), TileSS); - // restore %rax - // mov (%sp) %rax - addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm), GR64Cand), - StrideSS); + if (!GR64Cand) { + // restore %rax + // mov (%sp) %rax + addFrameReference( + BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm), GR64Cand), StrideSS); + } MI.eraseFromParent(); Changed = true; } diff --git a/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll b/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll index 4686361ad2fc..a0085afbaf02 100644 --- a/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll +++ b/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll @@ -44,12 +44,8 @@ define dso_local void @test1(ptr%buf) nounwind { ; CHECK-NEXT: tileloadd 3024(%rsp,%rax), %tmm3 # 1024-byte Folded Reload ; CHECK-NEXT: tileloadd (%rbx,%r15), %tmm0 ; CHECK-NEXT: tileloadd (%rbx,%r15), %tmm1 -; CHECK-NEXT: # implicit-def: $rax -; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill -; CHECK-NEXT: movabsq $64, %rax ; CHECK-NEXT: tilestored %tmm3, 1024(%rsp,%rax) # 1024-byte Folded Spill ; CHECK-NEXT: tileloadd {{[-0-9]+}}(%r{{[sb]}}p), %tmm2 # 1024-byte Folded Reload -; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload ; CHECK-NEXT: tdpbssd %tmm1, %tmm0, %tmm2 ; CHECK-NEXT: tilestored %tmm2, (%rbx,%r15) ; CHECK-NEXT: incl %r14d @@ -111,16 +107,10 @@ define dso_local void @test1(ptr%buf) nounwind { ; EGPR-NEXT: # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7b,0x4b,0x9c,0x04,0xd0,0x0b,0x00,0x00] ; EGPR-NEXT: tileloadd (%rbx,%r15), %tmm0 # EVEX TO VEX Compression encoding: [0xc4,0xa2,0x7b,0x4b,0x04,0x3b] ; EGPR-NEXT: tileloadd (%rbx,%r15), %tmm1 # EVEX TO VEX Compression encoding: [0xc4,0xa2,0x7b,0x4b,0x0c,0x3b] -; EGPR-NEXT: # implicit-def: $rax -; EGPR-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill -; EGPR-NEXT: # encoding: [0x48,0x89,0x84,0x24,0xb8,0x03,0x00,0x00] -; EGPR-NEXT: movabsq $64, %rax # encoding: [0x48,0xb8,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00] ; EGPR-NEXT: tilestored %tmm3, 1024(%rsp,%rax) # 1024-byte Folded Spill ; EGPR-NEXT: # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7a,0x4b,0x9c,0x04,0x00,0x04,0x00,0x00] ; EGPR-NEXT: tileloadd {{[-0-9]+}}(%r{{[sb]}}p), %tmm2 # 1024-byte Folded Reload ; EGPR-NEXT: # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7b,0x4b,0x94,0x24,0x00,0x04,0x00,0x00] -; EGPR-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload -; EGPR-NEXT: # encoding: [0x48,0x8b,0x84,0x24,0xb8,0x03,0x00,0x00] ; EGPR-NEXT: tdpbssd %tmm1, %tmm0, %tmm2 # encoding: [0xc4,0xe2,0x73,0x5e,0xd0] ; EGPR-NEXT: tilestored %tmm2, (%rbx,%r15) # EVEX TO VEX Compression encoding: [0xc4,0xa2,0x7a,0x4b,0x14,0x3b] ; EGPR-NEXT: incl %r14d # encoding: [0x41,0xff,0xc6] -- GitLab From 37fe3c6788a152dd88a54e2f22db05d9c7e53468 Mon Sep 17 00:00:00 2001 From: Abhishek Kulkarni <11399+adk9@users.noreply.github.com> Date: Sat, 20 Apr 2024 18:49:39 -0700 Subject: [PATCH 096/357] [mlir][python] Fix generation of Python bindings for `async` dialect (#75960) The Python bindings generated for "async" dialect didn't include any of the "async" dialect ops. This PR fixes issues with generation of Python bindings for "async" dialect and adds a test case to use them. --- .../mlir/Dialect/Async/IR/CMakeLists.txt | 1 + mlir/python/CMakeLists.txt | 4 +- .../mlir/dialects/async_dialect/__init__.py | 2 +- mlir/test/python/dialects/async_dialect.py | 16 ++++++- .../mlir/python/BUILD.bazel | 47 +++++++++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/mlir/include/mlir/Dialect/Async/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Async/IR/CMakeLists.txt index ebbf2df760fa..2525eee2a34e 100644 --- a/mlir/include/mlir/Dialect/Async/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Async/IR/CMakeLists.txt @@ -1,2 +1,3 @@ +set(LLVM_TARGET_DEFINITIONS AsyncOps.td) add_mlir_dialect(AsyncOps async) add_mlir_doc(AsyncOps AsyncDialect Dialects/ -gen-dialect-doc) diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt index ddd5c6b5ac74..a6c78880c8e7 100644 --- a/mlir/python/CMakeLists.txt +++ b/mlir/python/CMakeLists.txt @@ -79,7 +79,7 @@ declare_mlir_dialect_python_bindings( ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir" TD_FILE dialects/AsyncOps.td SOURCES_GLOB dialects/async_dialect/*.py - DIALECT_NAME async_dialect) + DIALECT_NAME async) declare_mlir_dialect_python_bindings( ADD_TO_PARENT MLIRPythonSources.Dialects @@ -591,7 +591,7 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Transform.Pybind declare_mlir_python_extension(MLIRPythonExtension.AsyncDialectPasses MODULE_NAME _mlirAsyncPasses - ADD_TO_PARENT MLIRPythonSources.Dialects.async_dialect + ADD_TO_PARENT MLIRPythonSources.Dialects.async ROOT_DIR "${PYTHON_SOURCE_DIR}" SOURCES AsyncPasses.cpp diff --git a/mlir/python/mlir/dialects/async_dialect/__init__.py b/mlir/python/mlir/dialects/async_dialect/__init__.py index dcf9d6cb2638..6a5ecfc20956 100644 --- a/mlir/python/mlir/dialects/async_dialect/__init__.py +++ b/mlir/python/mlir/dialects/async_dialect/__init__.py @@ -2,4 +2,4 @@ # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from .._async_dialect_ops_gen import * +from .._async_ops_gen import * diff --git a/mlir/test/python/dialects/async_dialect.py b/mlir/test/python/dialects/async_dialect.py index f6181cc76118..13e3c42e57c2 100644 --- a/mlir/test/python/dialects/async_dialect.py +++ b/mlir/test/python/dialects/async_dialect.py @@ -1,7 +1,8 @@ # RUN: %PYTHON %s | FileCheck %s from mlir.ir import * -import mlir.dialects.async_dialect +from mlir.dialects import arith +import mlir.dialects.async_dialect as async_dialect import mlir.dialects.async_dialect.passes from mlir.passmanager import * @@ -11,6 +12,19 @@ def run(f): f() +# CHECK-LABEL: TEST: testCreateGroupOp +@run +def testCreateGroupOp(): + with Context() as ctx, Location.unknown(): + module = Module.create() + with InsertionPoint(module.body): + i32 = IntegerType.get_signless(32) + group_size = arith.ConstantOp(i32, 4) + async_dialect.create_group(group_size) + # CHECK: %0 = "arith.constant"() <{value = 4 : i32}> : () -> i32 + # CHECK: %1 = "async.create_group"(%0) : (i32) -> !async.group + print(module) + def testAsyncPass(): with Context() as context: PassManager.parse("any(async-to-async-runtime)") diff --git a/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel index d6b0832f4c1a..3cc672476014 100644 --- a/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel @@ -331,6 +331,53 @@ filegroup( ], ) +##---------------------------------------------------------------------------## +# Async dialect. +##---------------------------------------------------------------------------## + +gentbl_filegroup( + name = "AsyncOpsPyGen", + tbl_outs = [ + ( + [ + "-gen-python-enum-bindings", + "-bind-dialect=async", + ], + "mlir/dialects/_async_enum_gen.py", + ), + ( + [ + "-gen-python-op-bindings", + "-bind-dialect=async", + ], + "mlir/dialects/_async_ops_gen.py", + ), + ], + tblgen = "//mlir:mlir-tblgen", + td_file = "mlir/dialects/AsyncOps.td", + deps = [ + "//mlir:AsyncOpsTdFiles", + "//mlir:OpBaseTdFiles", + ], +) + +filegroup( + name = "AsyncOpsPyFiles", + srcs = [ + ":AsyncOpsPyGen", + ], +) + +filegroup( + name = "AsyncOpsPackagePyFiles", + srcs = glob(["mlir/dialects/async_dialect/*.py"]), +) + +filegroup( + name = "AsyncOpsPackagePassesPyFiles", + srcs = glob(["mlir/dialects/async_dialect/passes/*.py"]), +) + ##---------------------------------------------------------------------------## # Arith dialect. ##---------------------------------------------------------------------------## -- GitLab From de1d4eb06bc22834fe8008769b4c9344a0a8330f Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sat, 20 Apr 2024 18:50:13 -0700 Subject: [PATCH 097/357] [memprof] Omit the key length for the call stack table (#89510) The call stack table has a constant key length, so we don't need to serialize or deserialize it for every key-data pair. Omitting the key length saves 0.64% of the indexed MemProf file size. Note that it's OK to change the format because Version2 is still under development. --- llvm/include/llvm/ProfileData/MemProf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index 59ef59fd33a3..aa6cdf198485 100644 --- a/llvm/include/llvm/ProfileData/MemProf.h +++ b/llvm/include/llvm/ProfileData/MemProf.h @@ -652,8 +652,8 @@ public: EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V) { using namespace support; endian::Writer LE(Out, llvm::endianness::little); + // We do not explicitly emit the key length because it is a constant. offset_type N = sizeof(K); - LE.write(N); offset_type M = sizeof(FrameId) * V.size(); LE.write(M); return std::make_pair(N, M); @@ -697,8 +697,8 @@ public: ReadKeyDataLength(const unsigned char *&D) { using namespace support; - offset_type KeyLen = - endian::readNext(D); + // We do not explicitly read the key length because it is a constant. + offset_type KeyLen = sizeof(external_key_type); offset_type DataLen = endian::readNext(D); return std::make_pair(KeyLen, DataLen); -- GitLab From 6cebd3577245a687947506ff423ea726ccd80849 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 20 Apr 2024 19:21:38 -0700 Subject: [PATCH 098/357] [RISCV] Remove extra indentation from RISCVProcessors.td. --- llvm/lib/Target/RISCV/RISCVProcessors.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVProcessors.td b/llvm/lib/Target/RISCV/RISCVProcessors.td index 3c86036e65fa..a4a5d9e96c27 100644 --- a/llvm/lib/Target/RISCV/RISCVProcessors.td +++ b/llvm/lib/Target/RISCV/RISCVProcessors.td @@ -44,7 +44,7 @@ class RISCVProcessorModel f, list tunef = [], string default_march = ""> - : ProcessorModel { + : ProcessorModel { string DefaultMarch = default_march; } @@ -52,7 +52,7 @@ class RISCVTuneProcessorModel tunef = [], list f = []> - : ProcessorModel; + : ProcessorModel; def GENERIC_RV32 : RISCVProcessorModel<"generic-rv32", NoSchedModel, -- GitLab From 811ffc049ff914e15116c25ca8db7b8bd9a8e186 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Sun, 21 Apr 2024 11:58:35 +0800 Subject: [PATCH 099/357] [tidy] update check list [NFC] --- clang-tools-extra/docs/clang-tidy/checks/list.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 8bc46acad56c..3a06d7c30c9b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -341,9 +341,9 @@ Clang-Tidy Checks :doc:`portability-std-allocator-const `, :doc:`readability-avoid-const-params-in-decls `, "Yes" :doc:`readability-avoid-nested-conditional-operator `, - :doc:`readability-avoid-return-with-void-value `, + :doc:`readability-avoid-return-with-void-value `, "Yes" :doc:`readability-avoid-unconditional-preprocessor-if `, - :doc:`readability-braces-around-statements `, "Yes" + :doc:`readability-braces-around-statements `, :doc:`readability-const-return-type `, "Yes" :doc:`readability-container-contains `, "Yes" :doc:`readability-container-data-pointer `, "Yes" @@ -529,12 +529,12 @@ Clang-Tidy Checks :doc:`cppcoreguidelines-non-private-member-variables-in-classes `, :doc:`misc-non-private-member-variables-in-classes `, :doc:`cppcoreguidelines-use-default-member-init `, :doc:`modernize-use-default-member-init `, "Yes" :doc:`fuchsia-header-anon-namespaces `, :doc:`google-build-namespaces `, - :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" + :doc:`google-readability-braces-around-statements `, :doc:`readability-braces-around-statements `, :doc:`google-readability-function-size `, :doc:`readability-function-size `, :doc:`google-readability-namespace-comments `, :doc:`llvm-namespace-comment `, :doc:`hicpp-avoid-c-arrays `, :doc:`modernize-avoid-c-arrays `, :doc:`hicpp-avoid-goto `, :doc:`cppcoreguidelines-avoid-goto `, - :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, "Yes" + :doc:`hicpp-braces-around-statements `, :doc:`readability-braces-around-statements `, :doc:`hicpp-deprecated-headers `, :doc:`modernize-deprecated-headers `, "Yes" :doc:`hicpp-explicit-conversions `, :doc:`google-explicit-constructor `, "Yes" :doc:`hicpp-function-size `, :doc:`readability-function-size `, -- GitLab From cb7cb83010bbcd8e5325d81b6d80653c7b513516 Mon Sep 17 00:00:00 2001 From: zhongyunde 00443407 Date: Thu, 28 Mar 2024 21:39:30 -0400 Subject: [PATCH 100/357] [InstCombine] Add check to avoid dependent optimization order, NFC Since PR86428, foldPowiReassoc is called by both FMul and FDiv, as the optimization of FDiv is placed after the FMul, so now it is correct we don't add the checking of FDiv for powi(X, Y) / X. But, we may add more matching scenarios later, so add the checking opcode explicitly is easier to understand. --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index a0333b7db8f7..000d33a09197 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -582,6 +582,9 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { }; Value *X, *Y, *Z; + unsigned Opcode = I.getOpcode(); + assert((Opcode == Instruction::FMul || Opcode == Instruction::FDiv) && + "Unexpected opcode"); // powi(X, Y) * X --> powi(X, Y+1) // X * powi(X, Y) --> powi(X, Y+1) @@ -596,7 +599,7 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { // powi(x, y) * powi(x, z) -> powi(x, y + z) Value *Op0 = I.getOperand(0); Value *Op1 = I.getOperand(1); - if (I.isOnlyUserOfAnyOperand() && + if (Opcode == Instruction::FMul && I.isOnlyUserOfAnyOperand() && match(Op0, m_AllowReassoc( m_Intrinsic(m_Value(X), m_Value(Y)))) && match(Op1, m_AllowReassoc(m_Intrinsic(m_Specific(X), @@ -608,7 +611,7 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { // 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() && + if (Opcode == Instruction::FDiv && I.hasAllowReassoc() && I.hasNoNaNs() && match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic( m_Specific(Op1), m_Value(Y))))) && willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { -- GitLab From 56ca5ecf416ad0e57c5e3558159bd73e5d662476 Mon Sep 17 00:00:00 2001 From: zhongyunde 00443407 Date: Thu, 28 Mar 2024 22:18:37 -0400 Subject: [PATCH 101/357] [InstCombine] Optimize powi(X, Y)/ (X * Z) with Ofast foldFDivPowDivisor can address A / powi(x, y) to A * powi(x, -y), while for small const value y, for example y=2, the instcombine will transform powi(x, 2) to fmul x, x, so it is not optimal for A / powi(x, 2). Fix https://github.com/llvm/llvm-project/issues/77171 --- .../InstCombine/InstCombineMulDivRem.cpp | 54 +++++--- llvm/test/Transforms/InstCombine/powi.ll | 115 ++++++++++++++++++ 2 files changed, 152 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 000d33a09197..4ed4c36e21e0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -576,9 +576,10 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { Value *Y, Value *Z) { InstCombiner::BuilderTy &Builder = IC.Builder; Value *YZ = Builder.CreateAdd(Y, Z); - auto *NewPow = Builder.CreateIntrinsic( + Instruction *NewPow = Builder.CreateIntrinsic( Intrinsic::powi, {X->getType(), YZ->getType()}, {X, YZ}, &I); - return IC.replaceInstUsesWith(I, NewPow); + + return NewPow; }; Value *X, *Y, *Z; @@ -592,8 +593,10 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { m_Value(X), m_Value(Y)))), m_Deferred(X)))) { Constant *One = ConstantInt::get(Y->getType(), 1); - if (willNotOverflowSignedAdd(Y, One, I)) - return createPowiExpr(I, *this, X, Y, One); + if (willNotOverflowSignedAdd(Y, One, I)) { + Instruction *NewPow = createPowiExpr(I, *this, X, Y, One); + return replaceInstUsesWith(I, NewPow); + } } // powi(x, y) * powi(x, z) -> powi(x, y + z) @@ -604,19 +607,36 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { m_Intrinsic(m_Value(X), m_Value(Y)))) && match(Op1, m_AllowReassoc(m_Intrinsic(m_Specific(X), m_Value(Z)))) && - 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 (Opcode == Instruction::FDiv && I.hasAllowReassoc() && I.hasNoNaNs() && - 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); + Y->getType() == Z->getType()) { + Instruction *NewPow = createPowiExpr(I, *this, X, Y, Z); + return replaceInstUsesWith(I, NewPow); + } + + if (Opcode == Instruction::FDiv && I.hasAllowReassoc() && I.hasNoNaNs()) { + // 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 (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()); + Instruction *NewPow = createPowiExpr(I, *this, Op1, Y, NegOne); + return replaceInstUsesWith(I, NewPow); + } + + // powi(X, Y) / (X * Z) --> powi(X, Y-1) / Z + // 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 (match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic( + m_Value(X), m_Value(Y))))) && + match(Op1, m_AllowReassoc(m_c_FMul(m_Specific(X), m_Value(Z)))) && + willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { + Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType()); + auto *NewPow = createPowiExpr(I, *this, X, Y, NegOne); + return BinaryOperator::CreateFDivFMF(NewPow, Z, &I); + } } return nullptr; diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll index 6c0575e8b719..d76f92c1849a 100644 --- a/llvm/test/Transforms/InstCombine/powi.ll +++ b/llvm/test/Transforms/InstCombine/powi.ll @@ -401,6 +401,121 @@ define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) { ret double %div } +; powi(X,C1)/ (X * Z) --> powi(X,C1 - 1)/ Z +define double @fdiv_fmul_powi(double %a, double %z) { +; CHECK-LABEL: @fdiv_fmul_powi( +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc nnan double @llvm.powi.f64.i32(double [[A:%.*]], i32 4) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5) + %square = fmul reassoc double %z, %a + %div = fdiv reassoc nnan double %pow, %square + ret double %div +} + +; powi(X, 5)/ (X * X) --> powi(X, 4)/ X -> powi(X, 3) +define double @fdiv_fmul_powi_2(double %a) { +; CHECK-LABEL: @fdiv_fmul_powi_2( +; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan double @llvm.powi.f64.i32(double [[A:%.*]], i32 3) +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5) + %square = fmul reassoc double %a, %a + %div = fdiv reassoc nnan double %pow, %square + ret double %div +} + +define <2 x float> @fdiv_fmul_powi_vector(<2 x float> %a) { +; CHECK-LABEL: @fdiv_fmul_powi_vector( +; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan <2 x float> @llvm.powi.v2f32.i32(<2 x float> [[A:%.*]], i32 3) +; CHECK-NEXT: ret <2 x float> [[DIV]] +; + %pow = call reassoc <2 x float> @llvm.powi.v2f32.i32(<2 x float> %a, i32 5) + %square = fmul reassoc <2 x float> %a, %a + %div = fdiv reassoc nnan <2 x float> %pow, %square + ret <2 x float> %div +} + +; Negative test +define double @fdiv_fmul_powi_missing_reassoc1(double %a) { +; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc1( +; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5) +; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan double [[POW]], [[SQUARE]] +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5) + %square = fmul reassoc double %a, %a + %div = fdiv nnan double %pow, %square + ret double %div +} + +define double @fdiv_fmul_powi_missing_reassoc2(double %a) { +; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc2( +; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5) +; CHECK-NEXT: [[SQUARE:%.*]] = fmul double [[A]], [[A]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]] +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5) + %square = fmul double %a, %a + %div = fdiv reassoc nnan double %pow, %square + ret double %div +} + +define double @fdiv_fmul_powi_missing_reassoc3(double %a) { +; CHECK-LABEL: @fdiv_fmul_powi_missing_reassoc3( +; CHECK-NEXT: [[POW:%.*]] = call double @llvm.powi.f64.i32(double [[A:%.*]], i32 5) +; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]] +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call double @llvm.powi.f64.i32(double %a, i32 5) + %square = fmul reassoc double %a, %a + %div = fdiv reassoc nnan double %pow, %square + ret double %div +} + +define double @fdiv_fmul_powi_missing_nnan(double %a) { +; CHECK-LABEL: @fdiv_fmul_powi_missing_nnan( +; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5) +; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[POW]], [[SQUARE]] +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5) + %square = fmul reassoc double %a, %a + %div = fdiv reassoc double %pow, %square + ret double %div +} + +define double @fdiv_fmul_powi_negative_wrap(double noundef %x) { +; CHECK-LABEL: @fdiv_fmul_powi_negative_wrap( +; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 -2147483648) +; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]] +; CHECK-NEXT: ret double [[MUL]] +; + %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 -2147483648) ; INT_MIN + %mul = fmul reassoc double %p1, %x + ret double %mul +} + +define double @fdiv_fmul_powi_multi_use(double %a) { +; CHECK-LABEL: @fdiv_fmul_powi_multi_use( +; CHECK-NEXT: [[POW:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[A:%.*]], i32 5) +; CHECK-NEXT: tail call void @use(double [[POW]]) +; CHECK-NEXT: [[SQUARE:%.*]] = fmul reassoc double [[A]], [[A]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[POW]], [[SQUARE]] +; CHECK-NEXT: ret double [[DIV]] +; + %pow = call reassoc double @llvm.powi.f64.i32(double %a, i32 5) + tail call void @use(double %pow) + %square = fmul reassoc double %a, %a + %div = fdiv reassoc nnan double %pow, %square + ret double %div +} + ; powi(X, Y) * X --> powi(X, Y+1) define double @powi_fmul_powi_x(double noundef %x) { ; CHECK-LABEL: @powi_fmul_powi_x( -- GitLab From fa01d04c9b9a3c8454194a36a0e64daf43cddaf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 21 Apr 2024 08:30:19 +0200 Subject: [PATCH 102/357] [clang][Interp][NFC] Change pointer offset to uint64 To accomodate for recent changes in array index calculations. --- clang/lib/AST/Interp/Pointer.cpp | 4 ++-- clang/lib/AST/Interp/Pointer.h | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index e163e658d462..5ef31671ae7b 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -23,7 +23,7 @@ Pointer::Pointer(Block *Pointee) : Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(), Pointee->getDescriptor()->getMetadataSize()) {} -Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset) +Pointer::Pointer(Block *Pointee, uint64_t BaseAndOffset) : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {} Pointer::Pointer(const Pointer &P) @@ -34,7 +34,7 @@ Pointer::Pointer(const Pointer &P) PointeeStorage.BS.Pointee->addPointer(this); } -Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset) +Pointer::Pointer(Block *Pointee, unsigned Base, uint64_t Offset) : Offset(Offset), StorageKind(Storage::Block) { assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base"); diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index b4475577b746..c4d701bc71b7 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -89,10 +89,10 @@ public: PointeeStorage.Int.Desc = nullptr; } Pointer(Block *B); - Pointer(Block *B, unsigned BaseAndOffset); + Pointer(Block *B, uint64_t BaseAndOffset); Pointer(const Pointer &P); Pointer(Pointer &&P); - Pointer(uint64_t Address, const Descriptor *Desc, unsigned Offset = 0) + Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0) : Offset(Offset), StorageKind(Storage::Int) { PointeeStorage.Int.Value = Address; PointeeStorage.Int.Desc = Desc; @@ -134,14 +134,14 @@ public: std::optional toRValue(const Context &Ctx) const; /// Offsets a pointer inside an array. - [[nodiscard]] Pointer atIndex(unsigned Idx) const { + [[nodiscard]] Pointer atIndex(uint64_t Idx) const { if (isIntegralPointer()) return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx); if (asBlockPointer().Base == RootPtrMark) return Pointer(asBlockPointer().Pointee, RootPtrMark, getDeclDesc()->getSize()); - unsigned Off = Idx * elemSize(); + uint64_t Off = Idx * elemSize(); if (getFieldDesc()->ElemDesc) Off += sizeof(InlineDescriptor); else @@ -630,7 +630,7 @@ private: friend class DeadBlock; friend struct InitMap; - Pointer(Block *Pointee, unsigned Base, unsigned Offset); + Pointer(Block *Pointee, unsigned Base, uint64_t Offset); /// Returns the embedded descriptor preceding a field. InlineDescriptor *getInlineDesc() const { @@ -656,7 +656,7 @@ private: } /// Offset into the storage. - unsigned Offset = 0; + uint64_t Offset = 0; /// Previous link in the pointer chain. Pointer *Prev = nullptr; -- GitLab From e32c4dfefcd1d54eb8f353f6fa08ef6f06d0fcc4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 21 Apr 2024 16:02:34 +0900 Subject: [PATCH 103/357] Revert "[X86] X86LowerTileCopy: Find dead register to use to prevent save-reload of tile register (#83628)" This reverts commit 34acbb3801515f9f41cc2d790d26072eb004ac46. This change causes major compile-time regressions. --- llvm/lib/Target/X86/X86LowerTileCopy.cpp | 61 ++++++------------- .../CodeGen/X86/AMX/amx-lower-tile-copy.ll | 10 +++ 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/llvm/lib/Target/X86/X86LowerTileCopy.cpp b/llvm/lib/Target/X86/X86LowerTileCopy.cpp index 2ca21e69e591..e7afc49240e5 100644 --- a/llvm/lib/Target/X86/X86LowerTileCopy.cpp +++ b/llvm/lib/Target/X86/X86LowerTileCopy.cpp @@ -20,7 +20,6 @@ #include "X86InstrBuilder.h" #include "X86InstrInfo.h" #include "X86Subtarget.h" -#include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -73,16 +72,10 @@ FunctionPass *llvm::createX86LowerTileCopyPass() { bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { const X86Subtarget &ST = MF.getSubtarget(); const X86InstrInfo *TII = ST.getInstrInfo(); - const TargetRegisterInfo *TRI = ST.getRegisterInfo(); - BitVector GR64Regs = - TRI->getAllocatableSet(MF, TRI->getRegClass(X86::GR64RegClassID)); bool Changed = false; for (MachineBasicBlock &MBB : MF) { - LiveRegUnits UsedRegs(*TRI); - UsedRegs.addLiveOuts(MBB); - for (MachineInstr &MI : llvm::make_early_inc_range(reverse(MBB))) { - UsedRegs.stepBackward(MI); + for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { if (!MI.isCopy()) continue; MachineOperand &DstMO = MI.getOperand(0); @@ -92,41 +85,27 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { if (!X86::TILERegClass.contains(DstReg, SrcReg)) continue; + const TargetRegisterInfo *TRI = ST.getRegisterInfo(); // Allocate stack slot for tile register unsigned Size = TRI->getSpillSize(X86::TILERegClass); Align Alignment = TRI->getSpillAlign(X86::TILERegClass); int TileSS = MF.getFrameInfo().CreateSpillStackObject(Size, Alignment); + // Allocate stack slot for stride register + Size = TRI->getSpillSize(X86::GR64RegClass); + Alignment = TRI->getSpillAlign(X86::GR64RegClass); + int StrideSS = MF.getFrameInfo().CreateSpillStackObject(Size, Alignment); - int StrideSS = 0; - - // Pick a killed register to avoid a save/reload. - Register GR64Cand = X86::NoRegister; - for (auto RegT : GR64Regs.set_bits()) { - if (UsedRegs.available(RegT)) { - GR64Cand = RegT; - break; - } - } + // TODO: Pick a killed regiter to avoid save/reload. There is problem + // to get live interval in this stage. + Register GR64Cand = X86::RAX; const DebugLoc &DL = MI.getDebugLoc(); - if (GR64Cand) { - // mov 64 %reg - BuildMI(MBB, MI, DL, TII->get(X86::MOV64ri), GR64Cand).addImm(64); - } else { - // No available register? Save RAX and reload it after use. - - // Allocate stack slot for stride register - Size = TRI->getSpillSize(X86::GR64RegClass); - Alignment = TRI->getSpillAlign(X86::GR64RegClass); - StrideSS = MF.getFrameInfo().CreateSpillStackObject(Size, Alignment); - - // mov %reg (%sp) - addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV64mr)), - StrideSS) - .addReg(X86::RAX); - // mov 64 %reg - BuildMI(MBB, MI, DL, TII->get(X86::MOV64ri), X86::RAX).addImm(64); - } + // mov %rax (%sp) + BuildMI(MBB, MI, DL, TII->get(X86::IMPLICIT_DEF), GR64Cand); + addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV64mr)), StrideSS) + .addReg(GR64Cand); + // mov 64 %rax + BuildMI(MBB, MI, DL, TII->get(X86::MOV64ri), GR64Cand).addImm(64); // tilestored %tmm, (%sp, %idx) #define GET_EGPR_IF_ENABLED(OPC) (ST.hasEGPR() ? OPC##_EVEX : OPC) unsigned Opc = GET_EGPR_IF_ENABLED(X86::TILESTORED); @@ -141,12 +120,10 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) { #undef GET_EGPR_IF_ENABLED NewMI = addFrameReference(BuildMI(MBB, MI, DL, TII->get(Opc), DstReg), TileSS); - if (!GR64Cand) { - // restore %rax - // mov (%sp) %rax - addFrameReference( - BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm), GR64Cand), StrideSS); - } + // restore %rax + // mov (%sp) %rax + addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm), GR64Cand), + StrideSS); MI.eraseFromParent(); Changed = true; } diff --git a/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll b/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll index a0085afbaf02..4686361ad2fc 100644 --- a/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll +++ b/llvm/test/CodeGen/X86/AMX/amx-lower-tile-copy.ll @@ -44,8 +44,12 @@ define dso_local void @test1(ptr%buf) nounwind { ; CHECK-NEXT: tileloadd 3024(%rsp,%rax), %tmm3 # 1024-byte Folded Reload ; CHECK-NEXT: tileloadd (%rbx,%r15), %tmm0 ; CHECK-NEXT: tileloadd (%rbx,%r15), %tmm1 +; CHECK-NEXT: # implicit-def: $rax +; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; CHECK-NEXT: movabsq $64, %rax ; CHECK-NEXT: tilestored %tmm3, 1024(%rsp,%rax) # 1024-byte Folded Spill ; CHECK-NEXT: tileloadd {{[-0-9]+}}(%r{{[sb]}}p), %tmm2 # 1024-byte Folded Reload +; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload ; CHECK-NEXT: tdpbssd %tmm1, %tmm0, %tmm2 ; CHECK-NEXT: tilestored %tmm2, (%rbx,%r15) ; CHECK-NEXT: incl %r14d @@ -107,10 +111,16 @@ define dso_local void @test1(ptr%buf) nounwind { ; EGPR-NEXT: # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7b,0x4b,0x9c,0x04,0xd0,0x0b,0x00,0x00] ; EGPR-NEXT: tileloadd (%rbx,%r15), %tmm0 # EVEX TO VEX Compression encoding: [0xc4,0xa2,0x7b,0x4b,0x04,0x3b] ; EGPR-NEXT: tileloadd (%rbx,%r15), %tmm1 # EVEX TO VEX Compression encoding: [0xc4,0xa2,0x7b,0x4b,0x0c,0x3b] +; EGPR-NEXT: # implicit-def: $rax +; EGPR-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; EGPR-NEXT: # encoding: [0x48,0x89,0x84,0x24,0xb8,0x03,0x00,0x00] +; EGPR-NEXT: movabsq $64, %rax # encoding: [0x48,0xb8,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00] ; EGPR-NEXT: tilestored %tmm3, 1024(%rsp,%rax) # 1024-byte Folded Spill ; EGPR-NEXT: # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7a,0x4b,0x9c,0x04,0x00,0x04,0x00,0x00] ; EGPR-NEXT: tileloadd {{[-0-9]+}}(%r{{[sb]}}p), %tmm2 # 1024-byte Folded Reload ; EGPR-NEXT: # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7b,0x4b,0x94,0x24,0x00,0x04,0x00,0x00] +; EGPR-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; EGPR-NEXT: # encoding: [0x48,0x8b,0x84,0x24,0xb8,0x03,0x00,0x00] ; EGPR-NEXT: tdpbssd %tmm1, %tmm0, %tmm2 # encoding: [0xc4,0xe2,0x73,0x5e,0xd0] ; EGPR-NEXT: tilestored %tmm2, (%rbx,%r15) # EVEX TO VEX Compression encoding: [0xc4,0xa2,0x7a,0x4b,0x14,0x3b] ; EGPR-NEXT: incl %r14d # encoding: [0x41,0xff,0xc6] -- GitLab From aa22d4422ee031d3867290e6ec12985f87d9ea2f Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Sun, 21 Apr 2024 11:43:51 +0200 Subject: [PATCH 104/357] [Clang] Do not try to diagnose parameter packs in invalid pack expressions (#89257) In a pack expression, if the id-expression is not valid, do no try to detect whether it is a pack as that would lead to a crash trying to print a recovery expression. Fixes #88929 --- clang/lib/Sema/SemaTemplateVariadic.cpp | 8 +++++--- clang/test/SemaCXX/cxx2c-pack-indexing.cpp | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 4909414c0c78..a4b681ae4f00 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1085,9 +1085,11 @@ ExprResult Sema::ActOnPackIndexingExpr(Scope *S, Expr *PackExpression, SourceLocation RSquareLoc) { bool isParameterPack = ::isParameterPack(PackExpression); if (!isParameterPack) { - CorrectDelayedTyposInExpr(IndexExpr); - Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack) - << PackExpression; + if (!PackExpression->containsErrors()) { + CorrectDelayedTyposInExpr(IndexExpr); + Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack) + << PackExpression; + } return ExprError(); } ExprResult Res = diff --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp index e13635383b6c..606715e6aacf 100644 --- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp +++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp @@ -154,3 +154,9 @@ void f() { } } + +namespace GH88929 { + bool b = a...[0]; // expected-error {{use of undeclared identifier 'a'}} + using E = P...[0]; // expected-error {{unknown type name 'P'}} \ + // expected-error {{expected ';' after alias declaration}} +} -- GitLab From e095d978ba476c9624b4e72776089ea7301fa657 Mon Sep 17 00:00:00 2001 From: Gaurav Shukla Date: Sun, 21 Apr 2024 17:07:02 +0530 Subject: [PATCH 105/357] [MLIR] Generalize expand_shape to take shape as explicit input (#69267) This patch generalizes tensor.expand_shape and memref.expand_shape to consume the output shape as a list of SSA values. This enables us to implement generic reshape operations with dynamic shapes using collapse_shape/expand_shape pairs. The output_shape input to expand_shape follows the static/dynamic representation that's also used in `tensor.extract_slice`. Differential Revision: https://reviews.llvm.org/D140821 Co-authored-by: Ramiro Leal-Cavazos --- .../mlir/Dialect/MemRef/IR/MemRefOps.td | 80 +++-- .../mlir/Dialect/Tensor/IR/TensorOps.td | 79 +++-- .../mlir/Dialect/Utils/ReshapeOpsUtils.h | 58 +++- .../mlir/Dialect/Utils/StaticValueUtils.h | 5 +- .../Conversion/TosaToLinalg/TosaToLinalg.cpp | 1 - mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 16 +- .../Transforms/ConvertConv2DToImg2Col.cpp | 2 +- .../Transforms/DataLayoutPropagation.cpp | 10 +- .../Linalg/Transforms/DropUnitDims.cpp | 13 +- .../Linalg/Transforms/ElementwiseOpFusion.cpp | 67 ++-- .../Linalg/Transforms/SplitReduction.cpp | 1 + .../Dialect/Linalg/Transforms/Transforms.cpp | 8 +- mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 82 ++++- .../Transforms/SparseTensorRewriting.cpp | 11 +- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 85 ++++- .../BufferizableOpInterfaceImpl.cpp | 3 + .../Transforms/PackAndUnpackPatterns.cpp | 24 +- mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp | 83 ++++- mlir/lib/Dialect/Utils/StaticValueUtils.cpp | 7 +- .../expand-then-convert-to-llvm.mlir | 16 +- .../MemRefToLLVM/memref-to-llvm.mlir | 4 +- .../TosaToLinalg/tosa-to-linalg.mlir | 29 +- .../TosaToTensor/tosa-to-tensor.mlir | 114 +++++-- ...ot-bufferize-empty-tensor-elimination.mlir | 2 +- .../Linalg/bubble-up-extract-slice-op.mlir | 4 +- mlir/test/Dialect/Linalg/collapse-dim.mlir | 6 +- .../Linalg/convert-conv2d-to-img2col.mlir | 20 +- .../Linalg/data-layout-propagation.mlir | 30 +- .../Dialect/Linalg/drop-unit-extent-dims.mlir | 108 ++++--- .../Dialect/Linalg/flatten-elementwise.mlir | 2 +- .../fuse-with-reshape-by-collapsing.mlir | 101 +++--- .../Dialect/Linalg/fusion-push-reshape.mlir | 24 +- .../Linalg/reshape_control_fusion.mlir | 2 +- mlir/test/Dialect/Linalg/reshape_fusion.mlir | 292 ++++++++++++------ .../resolve-shaped-type-result-dims.mlir | 5 +- .../Linalg/transform-op-split-reduction.mlir | 28 +- .../Linalg/vectorization-with-patterns.mlir | 4 +- mlir/test/Dialect/MemRef/canonicalize.mlir | 35 +-- .../MemRef/expand-strided-metadata.mlir | 16 +- .../Dialect/MemRef/fold-memref-alias-ops.mlir | 22 +- mlir/test/Dialect/MemRef/invalid.mlir | 38 +-- mlir/test/Dialect/MemRef/ops.mlir | 72 +++-- .../Dialect/MemRef/runtime-verification.mlir | 5 +- .../Dialect/SparseTensor/sparse_reshape.mlir | 12 +- mlir/test/Dialect/Tensor/bufferize.mlir | 24 +- mlir/test/Dialect/Tensor/canonicalize.mlir | 112 ++++--- mlir/test/Dialect/Tensor/fold-empty-op.mlir | 5 +- .../Tensor/fold-reassociative-reshapes.mlir | 6 +- mlir/test/Dialect/Tensor/invalid.mlir | 21 +- mlir/test/Dialect/Tensor/ops.mlir | 18 +- .../Dialect/Tensor/simplify-pack-unpack.mlir | 14 +- .../llvm-project-overlay/mlir/BUILD.bazel | 1 + 52 files changed, 1193 insertions(+), 634 deletions(-) diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td index 39e66cd9e6e5..14b8d95ea15b 100644 --- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td +++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td @@ -1548,7 +1548,6 @@ def MemRef_ReshapeOp: MemRef_Op<"reshape", [ class MemRef_ReassociativeReshapeOp traits = []> : MemRef_Op, - Arguments<(ins AnyStridedMemRef:$src, IndexListArrayAttr:$reassociation)>, Results<(outs AnyStridedMemRef:$result)>{ code commonExtraClassDeclaration = [{ @@ -1573,10 +1572,6 @@ class MemRef_ReassociativeReshapeOp traits = []> : Value getViewSource() { return getSrc(); } }]; - let assemblyFormat = [{ - $src $reassociation attr-dict `:` type($src) `into` type($result) - }]; - let hasFolder = 1; let hasCanonicalizer = 1; let hasVerifier = 1; @@ -1598,14 +1593,10 @@ def MemRef_ExpandShapeOp : MemRef_ReassociativeReshapeOp<"expand_shape", [ Example: ```mlir - %r = memref.expand_shape %0 [[0, 1], [2]] - : memref into memref + %r = memref.expand_shape %0 [[0, 1], [2]] output_shape [%sz0, %sz1, 32] + : memref into memref ``` - At most one dimension of a reassociation group (e.g., [0, 1] above) may be - dynamic in the result type. Otherwise, the op would be ambiguous, as it - would not be clear how the source dimension is extended. - If an op can be statically proven to be invalid (e.g, an expansion from `memref<10xf32>` to `memref<2x6xf32>`), it is rejected by the verifier. If it cannot statically be proven invalid (e.g., the full example above; it is @@ -1622,41 +1613,80 @@ def MemRef_ExpandShapeOp : MemRef_ReassociativeReshapeOp<"expand_shape", [ there must be a dynamic result dimension in the corresponding reassociation group. Same for strides. + The representation for the output shape supports a partially-static + specification via attributes specified through the `static_output_shape` + argument. A special sentinel value `ShapedType::kDynamic` encodes that the + corresponding entry has a dynamic value. There must be exactly as many SSA + inputs in `output_shape` as there are `ShapedType::kDynamic` entries in + `static_output_shape`. + Note: This op currently assumes that the inner strides are of the source/result layout map are the faster-varying ones. }]; + let arguments = (ins AnyStridedMemRef:$src, IndexListArrayAttr:$reassociation, + Variadic:$output_shape, + DenseI64ArrayAttr:$static_output_shape); + + let assemblyFormat = [{ + $src $reassociation `output_shape` + custom($output_shape, $static_output_shape) attr-dict `:` + type($src) `into` type($result) + }]; + let builders = [ // Builders using ReassociationIndices. OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - CArg<"ArrayRef", "{}">:$attrs), + "ArrayRef":$outputShape)>, + + // It will infer output shape using inferOutputShape() method. + OpBuilder<(ins "Type":$resultType, "Value":$src, + "ArrayRef":$reassociation)>, + + // Builder using ReassociationExprs. + OpBuilder<(ins "Type":$resultType, "Value":$src, + "ArrayRef":$reassociation), [{ - build($_builder, $_state, resultType, src, attrs); - $_state.addAttribute("reassociation", - getReassociationIndicesAttribute($_builder, reassociation)); + auto reassociationIndices = + convertReassociationMapsToIndices(reassociation); + build($_builder, $_state, resultType, src, reassociationIndices); }]>, - // Builder using ReassociationExprs. OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - CArg<"ArrayRef", "{}">:$attrs), + "ArrayRef":$outputShape), [{ auto reassociationMaps = - convertReassociationMapsToIndices($_builder, reassociation); - build($_builder, $_state, resultType, src, reassociationMaps, attrs); + convertReassociationMapsToIndices(reassociation); + build($_builder, $_state, resultType, src, reassociationMaps, + outputShape); }]>, + // Builder that infers the result layout map. The result shape must be + // specified. Otherwise, the op may be ambiguous. The output shape for + // the op will be inferred using the inferOutputShape() method. + OpBuilder<(ins "ArrayRef":$resultShape, "Value":$src, + "ArrayRef":$reassociation)>, + // Builder that infers the result layout map. The result shape must be // specified. Otherwise, the op may be ambiguous. OpBuilder<(ins "ArrayRef":$resultShape, "Value":$src, - "ArrayRef":$reassociation)> + "ArrayRef":$reassociation, + "ArrayRef":$outputShape)> ]; let extraClassDeclaration = commonExtraClassDeclaration # [{ static FailureOr computeExpandedType( MemRefType srcType, ArrayRef resultShape, ArrayRef reassociation); + + // Infer the output shape for a memref.expand_shape when it is possible + // to do so. + static FailureOr> inferOutputShape( + OpBuilder &b, Location loc, MemRefType expandedType, + ArrayRef reassociation, + ArrayRef inputShape); }]; let hasVerifier = 1; @@ -1707,6 +1737,12 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ source/result layout map are the faster-varying ones. }]; + let arguments = (ins AnyStridedMemRef:$src, IndexListArrayAttr:$reassociation); + + let assemblyFormat = [{ + $src $reassociation attr-dict `:` type($src) `into` type($result) + }]; + let builders = [ // Builders for a contracting reshape whose result type is computed from // `src` and `reassociation`. @@ -1718,7 +1754,7 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices($_builder, reassociation); + convertReassociationMapsToIndices(reassociation); build($_builder, $_state, src, reassociationMaps, attrs); }]>, @@ -1736,7 +1772,7 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices($_builder, reassociation); + convertReassociationMapsToIndices(reassociation); build($_builder, $_state, resultType, src, reassociationMaps, attrs); }]> ]; diff --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td index cf7f3e89079c..a403e89a39f9 100644 --- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td +++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td @@ -1062,8 +1062,7 @@ class Tensor_ReassociativeReshapeOp traits = []> : Tensor_Op, Pure])>, - Arguments<(ins AnyRankedTensor:$src, IndexListArrayAttr:$reassociation)>, - Results<(outs AnyRankedTensor:$result)> { + Results<(outs AnyTensor:$result)> { code commonExtraClassDeclaration = [{ static StringRef getReassociationAttrStrName() { return "reassociation"; } @@ -1086,10 +1085,6 @@ class Tensor_ReassociativeReshapeOp traits = []> : } }]; - let assemblyFormat = [{ - $src $reassociation attr-dict `:` type($src) `into` type($result) - }]; - let hasFolder = 1; let hasCanonicalizer = 1; let hasVerifier = 1; @@ -1102,43 +1097,75 @@ def Tensor_ExpandShapeOp : Tensor_ReassociativeReshapeOp<"expand_shape"> { rank than the operand `src` whose dimension sizes are a reassociation of `src`. - A reassociation is defined as a continuous grouping of dimensions. It is - represented with an array of DenseI64ArrayAttr attribute. Entries in the - array are referred to as reassociation maps. + A reassociation is defined as a continuous grouping of dimensions and is + represented with an array of DenseI64ArrayAttr attribute. The reassociation + maps applied to the result tensor with the higher rank must result in the + operand tensor with the smaller rank. - The reassociation maps are applied to the result shape to obtain the operand - shape. + The representation for the output shape supports a partially-static + specification via attributes specified through the `static_output_shape` + argument. A special sentinel value `ShapedType::kDynamic` encodes that the + corresponding entry has a dynamic value. There must be exactly as many SSA + inputs in `output_shape` as there are `ShapedType::kDynamic` entries in + `static_output_shape`. Example: ```mlir // Dimension expansion i -> (i', j') and (k) -> (k') - %b = tensor.expand_shape %a [[0, 1], [2]] - : tensor into tensor + %b = tensor.expand_shape %a [[0, 1], [2]] output_shape [%sz0, %sz1, 32] + : tensor into tensor ``` }]; + + let arguments = (ins AnyTensor:$src, IndexListArrayAttr:$reassociation, + Variadic:$output_shape, + DenseI64ArrayAttr:$static_output_shape); + + let assemblyFormat = [{ + $src $reassociation `output_shape` + custom($output_shape, $static_output_shape) attr-dict `:` + type($src) `into` type($result) + }]; + let builders = [ // Builders using ReassociationIndices. OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - CArg<"ArrayRef", "{}">:$attrs), + "ArrayRef":$outputShape)>, + + // It will infer output shape using inferOutputShape() method. + OpBuilder<(ins "Type":$resultType, "Value":$src, + "ArrayRef":$reassociation)>, + + // Builder using ReassociationExprs. + OpBuilder<(ins "Type":$resultType, "Value":$src, + "ArrayRef":$reassociation), [{ - build($_builder, $_state, resultType, src, attrs); - $_state.addAttribute("reassociation", - getReassociationIndicesAttribute($_builder, reassociation)); + auto reassociationIndices = + convertReassociationMapsToIndices(reassociation); + build($_builder, $_state, resultType, src, reassociationIndices); }]>, OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - CArg<"ArrayRef", "{}">:$attrs), + "ArrayRef":$outputShape), [{ - auto reassociationMaps = - convertReassociationMapsToIndices($_builder, reassociation); - build($_builder, $_state, resultType, src, reassociationMaps, attrs); + auto reassociationIndices = + convertReassociationMapsToIndices(reassociation); + build($_builder, $_state, resultType, src, reassociationIndices, + outputShape); }]> ]; let extraClassDeclaration = commonExtraClassDeclaration # [{ int64_t getCorrespondingSourceDim(int64_t resultDim); + + // Infer the output shape for a tensor.expand_shape when it is possible + // to do so. + static FailureOr> inferOutputShape( + OpBuilder &b, Location loc, RankedTensorType expandedType, + ArrayRef reassociation, + ArrayRef inputShape); }]; let hasVerifier = 1; @@ -1146,6 +1173,7 @@ def Tensor_ExpandShapeOp : Tensor_ReassociativeReshapeOp<"expand_shape"> { def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { let summary = "operation to produce a tensor with a smaller rank"; + let arguments = (ins AnyTensor:$src, IndexListArrayAttr:$reassociation); let description = [{ The `tensor.collapse_shape` op produces a new tensor of lower (or equal) rank whose dimension sizes are a reassociation of the original `src` dimensions. @@ -1163,6 +1191,11 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { : tensor into tensor ``` }]; + + let assemblyFormat = [{ + $src $reassociation attr-dict `:` type($src) `into` type($result) + }]; + let builders = [ // Builders for a contracting reshape whose result type is computed from // `src` and `reassociation`. @@ -1174,7 +1207,7 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices($_builder, reassociation); + convertReassociationMapsToIndices(reassociation); build($_builder, $_state, src, reassociationMaps, attrs); }]>, @@ -1192,7 +1225,7 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices($_builder, reassociation); + convertReassociationMapsToIndices(reassociation); build($_builder, $_state, resultType, src, reassociationMaps, attrs); }]> ]; diff --git a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h index ae9824f728da..8a41a0a18b0a 100644 --- a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h +++ b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h @@ -30,6 +30,27 @@ using ReassociationExprs = SmallVector; /// Attribute name for the ArrayAttr which encodes reassociation indices. constexpr StringRef getReassociationAttrName() { return "reassociation"; } +// Infer the output shape for a {memref|tensor}.expand_shape when it is possible +// to do so. +// +// Note: This should *only* be used to implement +// `ExpandShapeOp::inferOutputShape` in both the memref and tensor namespaces. +// If you need to infer the output shape you should use the static method of +// `ExpandShapeOp` instead of calling this. +// +// `inputShape` is the shape of the tensor or memref being expanded as a +// sequence of SSA values or constants. `expandedType` is the output shape of +// the expand_shape operation. `reassociation` is the reassociation denoting +// the output dims each input dim is mapped to. +// +// Returns the output shape in `outputShape` and `staticOutputShape`, following +// the conventions for the output_shape and static_output_shape inputs to the +// expand_shape ops. +std::optional> +inferExpandShapeOutputShape(OpBuilder &b, Location loc, ShapedType expandedType, + ArrayRef reassociation, + ArrayRef inputShape); + /// Compose reassociation maps that are used in pair of reshape ops where one /// is a producer and other is the consumer. Only valid to use this method when /// both the producer and consumer are collapsing dimensions or both are @@ -62,7 +83,7 @@ getReassociationIndicesAttribute(OpBuilder &b, /// Convert Array> to Array>. SmallVector convertReassociationMapsToIndices( - OpBuilder &b, ArrayRef reassociationExprs); + ArrayRef reassociationExprs); /// Return the reassociations maps to use to reshape given the source type and /// the target type when possible. Return std::nullopt when this computation @@ -140,14 +161,11 @@ static LogicalResult verifyReshapeLikeTypes(Op op, T expandedType, op.getReassociationIndices(), isExpansion); } -/// Verify that shapes of the reshaped types using following rules -/// 1) if a dimension in the collapsed type is static, then the corresponding -/// dimensions in the expanded shape should be +/// Verify that shapes of the reshaped types using following rule: +/// if a dimension in the collapsed type is static, then the corresponding +/// dimensions in the expanded shape should be /// a) static /// b) the product should be same as the collaped shape. -/// 2) if a dimension in the collaped type is dynamic, one and only one of the -/// corresponding dimensions in the expanded type should be dynamic. This -/// rule is only needed with reshape operations that are expanding. LogicalResult reshapeLikeShapesAreCompatible( function_ref emitError, ArrayRef collapsedShape, ArrayRef expandedShape, @@ -156,9 +174,11 @@ LogicalResult reshapeLikeShapesAreCompatible( /// Returns true iff the type is a MemRefType and has a non-identity layout. bool hasNonIdentityLayout(Type type); +enum class ReshapeOpKind { kExpand, kCollapse }; + /// Pattern to collapse producer/consumer reshape ops that are both collapsing /// dimensions or are both expanding dimensions. -template +template struct ComposeReassociativeReshapeOps : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(ReshapeOpTy reshapeOp, @@ -181,8 +201,18 @@ struct ComposeReassociativeReshapeOps : public OpRewritePattern { rewriter.getContext()); if (!reassociationIndices) return failure(); - rewriter.replaceOpWithNewOp( - reshapeOp, resultType, srcReshapeOp.getSrc(), *reassociationIndices); + + if constexpr (opKind == ReshapeOpKind::kExpand) { + SmallVector outputShape( + getMixedValues(reshapeOp.getStaticOutputShape(), + reshapeOp.getOutputShape(), rewriter)); + rewriter.replaceOpWithNewOp( + reshapeOp, resultType, srcReshapeOp.getSrc(), *reassociationIndices, + outputShape); + } else { + rewriter.replaceOpWithNewOp( + reshapeOp, resultType, srcReshapeOp.getSrc(), *reassociationIndices); + } return success(); } }; @@ -215,7 +245,8 @@ struct ComposeReassociativeReshapeOps : public OpRewritePattern { // /// When `rank(srcType) < rank(resultType)`, then we just swap `reassociation_1` /// `reassociation_2` and produce `expand_shape`. -template +template struct ComposeCollapseOfExpandOp : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(CollapseOpTy collapseOp, @@ -322,8 +353,11 @@ struct ComposeExpandOfCollapseOp : public OpRewritePattern { if (!composedReassociation) return failure(); + SmallVector outputShape(getMixedValues( + expandOp.getStaticOutputShape(), expandOp.getOutputShape(), rewriter)); rewriter.replaceOpWithNewOp( - expandOp, resultType, collapseOp.getSrc(), *composedReassociation); + expandOp, resultType, collapseOp.getSrc(), *composedReassociation, + outputShape); return success(); } diff --git a/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h b/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h index 20f019666a2e..594bcf5dbb39 100644 --- a/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h +++ b/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h @@ -125,9 +125,8 @@ SmallVector getMixedValues(ArrayRef staticValues, /// Decompose a vector of mixed static or dynamic values into the /// corresponding pair of arrays. This is the inverse function of /// `getMixedValues`. -std::pair> -decomposeMixedValues(Builder &b, - const SmallVectorImpl &mixedValues); +std::pair, SmallVector> +decomposeMixedValues(const SmallVectorImpl &mixedValues); /// Helper to sort `values` according to matching `keys`. SmallVector diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp index b6b85cab5a38..7c068d2e94fc 100644 --- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp +++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp @@ -18,7 +18,6 @@ #include "mlir/Dialect/Math/IR/Math.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" -#include "mlir/Dialect/Tensor/Utils/Utils.h" #include "mlir/Dialect/Tosa/IR/TosaOps.h" #include "mlir/Dialect/Tosa/Utils/ConversionUtils.h" #include "mlir/Dialect/Utils/ReshapeOpsUtils.h" diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp index 9c5c58fa1fab..6fe0adb955c9 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -586,12 +586,20 @@ struct FoldFillWithTensorReshape : OpRewritePattern { return failure(); Location loc = oldFill.getLoc(); - auto newInit = rewriter.create( - loc, reshapeOp.getResultType(), oldFill.output(), - reshapeOp.getReassociation()); + TensorReshapeOp newInit; + if constexpr (std::is_same::value) { + + newInit = rewriter.create( + loc, reshapeOp.getResultType(), oldFill.output(), + reshapeOp.getReassociation(), reshapeOp.getOutputShape(), + reshapeOp.getStaticOutputShape()); + } else { + newInit = rewriter.create(loc, reshapeOp.getResultType(), + oldFill.output(), + reshapeOp.getReassociation()); + } rewriter.replaceOpWithNewOp(reshapeOp, ValueRange{oldFill.value()}, ValueRange{newInit}); - return success(); } }; diff --git a/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp b/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp index 420b04b3ee28..81d44ba04fa1 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp @@ -349,7 +349,7 @@ rewriteInIm2Col(RewriterBase &rewriter, SmallVector batchMatVecReassociationIndice = {{0, 1}, {2, 3}}; - Value batchMatVecResultReshaped = rewriter.create( + auto batchMatVecResultReshaped = rewriter.create( loc, transposedOutputTensor.getType(), batchMatVecResult.getResult(0), batchMatVecReassociationIndice); diff --git a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp index 7fd88dec71d4..9a2493a59e01 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @@ -757,7 +757,10 @@ pushDownUnPackOpThroughExpandShape(tensor::UnPackOp unPackOp, ArrayRef innerDimsPos = unPackOp.getInnerDimsPos(); ArrayRef outerDimsPerm = unPackOp.getOuterDimsPerm(); - ArrayRef dstShape = expandOp.getType().getShape(); + auto expandTy = expandOp.getType().dyn_cast(); + if (!expandTy) + return failure(); + ArrayRef dstShape = expandTy.getShape(); SmallVector reassocIndices = expandOp.getReassociationIndices(); // Project inner tile pos to the dim pos after expanding. For example, if dims @@ -796,9 +799,8 @@ pushDownUnPackOpThroughExpandShape(tensor::UnPackOp unPackOp, nextPos += 1; } - RankedTensorType newExpandType = - tensor::PackOp::inferPackedType(expandOp.getType(), innerTileSizes, - projectedInnerDimsPos, newOuterDimsPerm); + RankedTensorType newExpandType = tensor::PackOp::inferPackedType( + expandTy, innerTileSizes, projectedInnerDimsPos, newOuterDimsPerm); auto newExpandOp = rewriter.create( expandOp.getLoc(), newExpandType, unPackOp.getSource(), newReassocIndices); diff --git a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp index 023ea277bcf4..65efa18af18f 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @@ -23,6 +23,7 @@ #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Tensor/Transforms/Transforms.h" #include "mlir/Dialect/Tensor/Utils/Utils.h" +#include "mlir/Dialect/Utils/ReshapeOpsUtils.h" #include "mlir/IR/AffineExpr.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/BuiltinTypes.h" @@ -272,8 +273,9 @@ expandValue(RewriterBase &rewriter, Location loc, Value result, Value origDest, assert(rankReductionStrategy == ControlDropUnitDims::RankReductionStrategy::ReassociativeReshape && "unknown rank reduction strategy"); - return rewriter.create(loc, origResultType, result, - reassociation); + return rewriter + .create(loc, origResultType, result, reassociation) + .getResult(); } /// Collapse the given `value` so that the type matches the type of @@ -536,9 +538,10 @@ LogicalResult linalg::dropUnitDims(RewriterBase &rewriter, GenericOp genericOp, resultReplacements.push_back(result); continue; } - resultReplacements.push_back(expandValue(rewriter, loc, result, origDest, - reassociations[opOperandIndex], - options.rankReductionStrategy)); + Value expandedValue = expandValue(rewriter, loc, result, origDest, + reassociations[opOperandIndex], + options.rankReductionStrategy); + resultReplacements.push_back(expandedValue); } rewriter.replaceOp(genericOp, resultReplacements); diff --git a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp index 373e9cfc3ce7..bf3a737f1c2b 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @@ -625,14 +625,14 @@ LogicalResult ExpansionInfo::compute(LinalgOp linalgOp, return success(); } -/// Epanding the body of a linalg operation requires adaptations of the accessed -/// loop indices. Specifically, access of indices in the original operation need -/// to be replaced with linearizations of indices in the expanded op. That -/// requires the shape of the expanded dimensions to be static (at least all but -/// the most significant). For now check that these are all statically sized. -/// Note that this could be extended to handle dynamic case, but the -/// implementation below uses `affine.apply` which seems to have issues when the -/// shapes are not static. +/// Expanding the body of a linalg operation requires adaptations of the +/// accessed loop indices. Specifically, access of indices in the original +/// operation need to be replaced with linearizations of indices in the expanded +/// op. That requires the shape of the expanded dimensions to be static (at +/// least all but the most significant). For now check that these are all +/// statically sized. Note that this could be extended to handle dynamic case, +/// but the implementation below uses `affine.apply` which seems to have issues +/// when the shapes are not static. static LogicalResult isLinalgOpExpandable(LinalgOp linalgOp, const ExpansionInfo &expansionInfo, PatternRewriter &rewriter) { @@ -750,6 +750,31 @@ static void updateExpandedGenericOpRegion(PatternRewriter &rewriter, } } +/// Checks if a single dynamic dimension expanded into multiple dynamic +/// dimensions. +static LogicalResult +validateDynamicDimExpansion(LinalgOp linalgOp, + const ExpansionInfo &expansionInfo, + PatternRewriter &rewriter) { + for (unsigned i : llvm::seq(0, expansionInfo.getOrigOpNumDims())) { + ArrayRef expandedShape = expansionInfo.getExpandedShapeOfDim(i); + if (expandedShape.size() == 1) + continue; + bool foundDynamic = false; + for (int64_t shape : expandedShape) { + if (ShapedType::isDynamic(shape)) { + if (foundDynamic) { + return rewriter.notifyMatchFailure( + linalgOp, "cannot infer expanded shape with multiple dynamic " + "dims in the same reassociation group"); + } + foundDynamic = true; + } + } + } + return success(); +} + /// Implements the fusion of a tensor.collapse_shape or a tensor.expand_shape op /// and a generic op as explained in `isFusableWithReshapeByExpansion`. Assumes /// that those conditions have been satisfied. @@ -759,6 +784,8 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, PatternRewriter &rewriter) { assert(isFusableWithReshapeByDimExpansion(linalgOp, fusableOpOperand) && "preconditions for fuse operation failed"); + + Location loc = linalgOp.getLoc(); // Check if reshape is expanding or collapsing. auto expandingReshapeOp = dyn_cast(*reshapeOp); auto collapsingReshapeOp = dyn_cast(*reshapeOp); @@ -778,6 +805,11 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, expandedType.getShape(), collapsedType.getShape(), rewriter))) return std::nullopt; + // TODO: With the support of multiple dynamic dims expansion in + // tensor.expand_shape op, this case can be handled. + if (failed(validateDynamicDimExpansion(linalgOp, expansionInfo, rewriter))) + return std::nullopt; + if (failed(isLinalgOpExpandable(linalgOp, expansionInfo, rewriter))) return std::nullopt; @@ -816,15 +848,13 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, /*isExpandingReshape=*/true))) return std::nullopt; expandedOpOperands.push_back(rewriter.create( - linalgOp.getLoc(), expandedOperandType, opOperand->get(), - reassociation)); + loc, expandedOperandType, opOperand->get(), reassociation)); continue; } } expandedOpOperands.push_back(opOperand->get()); } - Location loc = linalgOp.getLoc(); SmallVector outputs; for (OpOperand &opOperand : linalgOp.getDpsInitsMutable()) { AffineMap indexingMap = linalgOp.getMatchingIndexingMap(&opOperand); @@ -843,8 +873,7 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, /*isExpandingReshape=*/true))) return std::nullopt; outputs.push_back(rewriter.create( - linalgOp.getLoc(), expandedOutputType, opOperand.get(), - reassociation)); + loc, expandedOutputType, opOperand.get(), reassociation)); } else { outputs.push_back(opOperand.get()); } @@ -1615,15 +1644,17 @@ FailureOr mlir::linalg::collapseOpIterationDims( op.getIndexingMapMatchingResult(originalResult.value()); SmallVector reassociation = getOperandReassociation(indexingMap, collapsingInfo); + Value result; if (isa(collapsedOpResult.getType())) { - Value result = rewriter.create( - loc, originalResultType, collapsedOpResult, reassociation); - results.push_back(result); + MemRefType expandShapeResultType = MemRefType::get( + originalResultType.getShape(), originalResultType.getElementType()); + result = rewriter.create( + loc, expandShapeResultType, collapsedOpResult, reassociation); } else { - Value result = rewriter.create( + result = rewriter.create( loc, originalResultType, collapsedOpResult, reassociation); - results.push_back(result); } + results.push_back(result); } else { results.push_back(collapsedOpResult); } diff --git a/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp b/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp index 6559c86c9e0f..5bfdbc6d0bb5 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp @@ -114,6 +114,7 @@ FailureOr mlir::linalg::splitReduction( Type newType = RankedTensorType::get( newShape, cast(operand->get().getType()).getElementType()); + Value newInput = b.create( loc, newType, operand->get(), reassociation); newInputs.push_back(newInput); diff --git a/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp b/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp index 2297bf5e3551..91dfac802ad6 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @@ -329,11 +329,13 @@ FailureOr linalg::lowerPack(RewriterBase &rewriter, /*transposeOp=*/nullptr}; } } + // 5. Expand from the padded result to the stripMinedShape. + auto expandShapeResultType = + RankedTensorType::Builder(packedTensorType).setShape(stripMinedShape); auto reshapeOp = rewriter.create( - loc, - RankedTensorType::Builder(packedTensorType).setShape(stripMinedShape), - padOp.getResult(), packingMetadata.reassociations); + loc, expandShapeResultType, padOp.getResult(), + packingMetadata.reassociations); // 6. Transpose stripMinedShape to packedShape. SmallVector transpPerm = diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp index 836dcb8f329e..ced7fdd0a90f 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -2237,6 +2237,44 @@ FailureOr ExpandShapeOp::computeExpandedType( srcType.getMemorySpace()); } +FailureOr> +ExpandShapeOp::inferOutputShape(OpBuilder &b, Location loc, + MemRefType expandedType, + ArrayRef reassociation, + ArrayRef inputShape) { + std::optional> outputShape = + inferExpandShapeOutputShape(b, loc, expandedType, reassociation, + inputShape); + if (!outputShape) + return failure(); + return *outputShape; +} + +void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, + Type resultType, Value src, + ArrayRef reassociation, + ArrayRef outputShape) { + auto [staticOutputShape, dynamicOutputShape] = + decomposeMixedValues(SmallVector(outputShape)); + build(builder, result, resultType.cast(), src, + getReassociationIndicesAttribute(builder, reassociation), + dynamicOutputShape, staticOutputShape); +} + +void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, + Type resultType, Value src, + ArrayRef reassociation) { + SmallVector inputShape = + getMixedSizes(builder, result.location, src); + MemRefType memrefResultTy = resultType.cast(); + FailureOr> outputShape = inferOutputShape( + builder, result.location, memrefResultTy, reassociation, inputShape); + // Failure of this assertion usually indicates presence of multiple + // dynamic dimensions in the same reassociation group. + assert(succeeded(outputShape) && "unable to infer output shape"); + build(builder, result, memrefResultTy, src, reassociation, *outputShape); +} + void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, ArrayRef resultShape, Value src, ArrayRef reassociation) { @@ -2250,6 +2288,20 @@ void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, build(builder, result, *resultType, src, reassociation); } +void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, + ArrayRef resultShape, Value src, + ArrayRef reassociation, + ArrayRef outputShape) { + // Only ranked memref source values are supported. + auto srcType = llvm::cast(src.getType()); + FailureOr resultType = + ExpandShapeOp::computeExpandedType(srcType, resultShape, reassociation); + // Failure of this assertion usually indicates a problem with the source + // type, e.g., could not get strides/offset. + assert(succeeded(resultType) && "could not compute layout"); + build(builder, result, *resultType, src, reassociation, outputShape); +} + LogicalResult ExpandShapeOp::verify() { MemRefType srcType = getSrcType(); MemRefType resultType = getResultType(); @@ -2266,7 +2318,7 @@ LogicalResult ExpandShapeOp::verify() { if (failed(verifyCollapsedShape(getOperation(), srcType.getShape(), resultType.getShape(), getReassociationIndices(), - /*allowMultipleDynamicDimsPerGroup=*/false))) + /*allowMultipleDynamicDimsPerGroup=*/true))) return failure(); // Compute expected result type (including layout map). @@ -2280,14 +2332,28 @@ LogicalResult ExpandShapeOp::verify() { return emitOpError("expected expanded type to be ") << *expectedResultType << " but found " << resultType; + if ((int64_t)getStaticOutputShape().size() != resultType.getRank()) + return emitOpError("expected number of static shape bounds to be equal to " + "the output rank (") + << resultType.getRank() << ") but found " + << getStaticOutputShape().size() << " inputs instead"; + + if ((int64_t)getOutputShape().size() != + llvm::count(getStaticOutputShape(), ShapedType::kDynamic)) + return emitOpError("mismatch in dynamic dims in output_shape and " + "static_output_shape: static_output_shape has ") + << llvm::count(getStaticOutputShape(), ShapedType::kDynamic) + << " dynamic dims while output_shape has " << getOutputShape().size() + << " values"; + return success(); } void ExpandShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add, - ComposeExpandOfCollapseOp>( - context); + results.add< + ComposeReassociativeReshapeOps, + ComposeExpandOfCollapseOp>(context); } /// Compute the layout map after collapsing a given source MemRef type with the @@ -2488,9 +2554,11 @@ public: void CollapseShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add, - ComposeCollapseOfExpandOp, - CollapseShapeOpMemRefCastFolder>(context); + results.add< + ComposeReassociativeReshapeOps, + ComposeCollapseOfExpandOp, + CollapseShapeOpMemRefCastFolder>(context); } OpFoldResult ExpandShapeOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp index 02375f54d715..a23a1dae449d 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp @@ -952,8 +952,15 @@ public: auto rtp = getRankedTensorType(op.getResult()); auto denseTp = RankedTensorType::get(rtp.getShape(), rtp.getElementType()); - auto reshape = rewriter.create(loc, denseTp, op.getSrc(), - op.getReassociation()); + ReshapeOp reshape; + if constexpr (std::is_same::value) { + reshape = rewriter.create( + loc, denseTp, op.getSrc(), op.getReassociation(), + op.getOutputShape(), op.getStaticOutputShape()); + } else { + reshape = rewriter.create(loc, denseTp, op.getSrc(), + op.getReassociation()); + } Value convert = rewriter.create(loc, rtp, reshape); rewriter.replaceOp(op, convert); return success(); diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index 3ff41ab22fbc..f2e6e81a044b 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -1641,6 +1641,44 @@ int64_t ExpandShapeOp::getCorrespondingSourceDim(int64_t resultDim) { llvm_unreachable("could not find reassociation group"); } +FailureOr> +ExpandShapeOp::inferOutputShape(OpBuilder &b, Location loc, + RankedTensorType expandedType, + ArrayRef reassociation, + ArrayRef inputShape) { + std::optional> outputShape = + inferExpandShapeOutputShape(b, loc, expandedType, reassociation, + inputShape); + if (!outputShape) + return failure(); + return *outputShape; +} + +void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, + Type resultType, Value src, + ArrayRef reassociation, + ArrayRef outputShape) { + auto [staticOutputShape, dynamicOutputShape] = + decomposeMixedValues(SmallVector(outputShape)); + build(builder, result, resultType.cast(), src, + getReassociationIndicesAttribute(builder, reassociation), + dynamicOutputShape, staticOutputShape); +} + +void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, + Type resultType, Value src, + ArrayRef reassociation) { + SmallVector inputShape = + getMixedSizes(builder, result.location, src); + auto tensorResultTy = resultType.cast(); + FailureOr> outputShape = inferOutputShape( + builder, result.location, tensorResultTy, reassociation, inputShape); + // Failure of this assertion usually indicates presence of multiple + // dynamic dimensions in the same reassociation group. + assert(succeeded(outputShape) && "unable to infer output shape"); + build(builder, result, tensorResultTy, src, reassociation, *outputShape); +} + SmallVector CollapseShapeOp::getReassociationMaps() { return getSymbolLessAffineMaps(getReassociationExprs()); } @@ -1724,7 +1762,24 @@ static LogicalResult verifyTensorReshapeOp(TensorReshapeOp op, } LogicalResult ExpandShapeOp::verify() { - return verifyTensorReshapeOp(*this, getResultType(), getSrcType()); + auto srcType = getSrcType(); + auto resultType = getResultType(); + + if ((int64_t)getStaticOutputShape().size() != resultType.getRank()) + return emitOpError("expected number of static shape dims to be equal to " + "the output rank (") + << resultType.getRank() << ") but found " + << getStaticOutputShape().size() << " inputs instead"; + + if ((int64_t)getOutputShape().size() != + llvm::count(getStaticOutputShape(), ShapedType::kDynamic)) + return emitOpError("mismatch in dynamic dims in output_shape and " + "static_output_shape: static_output_shape has ") + << llvm::count(getStaticOutputShape(), ShapedType::kDynamic) + << " dynamic dims while output_shape has " << getOutputShape().size() + << " values"; + + return verifyTensorReshapeOp(*this, resultType, srcType); } LogicalResult CollapseShapeOp::verify() { @@ -1908,23 +1963,25 @@ struct FoldDimOfCollapseShape : public OpRewritePattern { void ExpandShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add, - ComposeExpandOfCollapseOp, - FoldReshapeWithConstant, - FoldReshapeWithSplat, - FoldReshapeWithFromElements, FoldDimOfExpandShape, - FoldDimOfCollapseShape>(context); + results.add< + ComposeReassociativeReshapeOps, + ComposeExpandOfCollapseOp, + FoldReshapeWithConstant, + FoldReshapeWithSplat, + FoldReshapeWithFromElements, FoldDimOfExpandShape, + FoldDimOfCollapseShape>(context); } void CollapseShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results - .add, - ComposeCollapseOfExpandOp, - FoldReshapeWithConstant, - FoldReshapeWithSplat, - FoldReshapeWithFromElements, FoldCollapseOfCastOp>( - context); + results.add< + ComposeReassociativeReshapeOps, + ComposeCollapseOfExpandOp, + FoldReshapeWithConstant, + FoldReshapeWithSplat, + FoldReshapeWithFromElements, FoldCollapseOfCastOp>( + context); } OpFoldResult ExpandShapeOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp index 58ea4cc4da3c..d078a575f40d 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp @@ -338,6 +338,9 @@ struct ExpandShapeOpInterface // Memref result type is inferred by the builder based on reassociation // indices and result shape. + // TODO: Instead of inferring the output shape argument of + // memref.expand_shape op, use output_shape argument of tensor.expand_shape + // op. replaceOpWithNewBufferizedOp( rewriter, op, tensorResultType.getShape(), *buffer, expandShapeOp.getReassociationIndices()); diff --git a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp index 666ac56c6cd5..7011ce23b55a 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp @@ -52,12 +52,16 @@ static LogicalResult isPackOn1D(RewriterBase &rewriter, Operation *op, struct SimplifyPackToExpandShape : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; - Value insertExpand(RewriterBase &rewriter, Location loc, Value operand, - Type newOperandType, ArrayAttr reassociation) const { + FailureOr + insertExpand(RewriterBase &rewriter, Location loc, Value operand, + Type newOperandType, + ArrayRef reassociation) const { if (operand.getType() == newOperandType) return operand; - return rewriter.create(loc, newOperandType, operand, - reassociation); + return rewriter + .create(loc, newOperandType, operand, + reassociation) + .getResult(); } /// Returns success() if it is only packing on the innermost dimension. @@ -96,10 +100,14 @@ struct SimplifyPackToExpandShape : public OpRewritePattern { getReassociationIndicesForReshape(sourceType, destType); if (!reassociation) return failure(); - Value expanded = insertExpand( - rewriter, packOp.getLoc(), packOp.getSource(), destType, - getReassociationIndicesAttribute(rewriter, *reassociation)); - rewriter.replaceOp(packOp, expanded); + FailureOr expanded = + insertExpand(rewriter, packOp.getLoc(), packOp.getSource(), destType, + *reassociation); + if (failed(expanded)) { + return rewriter.notifyMatchFailure( + packOp, "unable to expand source of tensor.pack"); + } + rewriter.replaceOp(packOp, *expanded); return success(); } }; diff --git a/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp b/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp index 41c7af4593c7..6161faf7e30e 100644 --- a/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp +++ b/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp @@ -8,6 +8,7 @@ #include "mlir/Dialect/Utils/ReshapeOpsUtils.h" +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/Builders.h" @@ -16,6 +17,67 @@ using namespace mlir; +std::optional> +mlir::inferExpandShapeOutputShape(OpBuilder &b, Location loc, + ShapedType expandedType, + ArrayRef reassociation, + ArrayRef inputShape) { + + SmallVector outputShapeValues; + SmallVector outputShapeInts; + // For zero-rank inputs, all dims in result shape are unit extent. + if (inputShape.empty()) { + outputShapeInts.resize(expandedType.getRank(), 1); + return getMixedValues(outputShapeInts, outputShapeValues, b); + } + + // Check for all static shapes. + if (expandedType.hasStaticShape()) { + ArrayRef staticShape = expandedType.getShape(); + outputShapeInts.assign(staticShape.begin(), staticShape.end()); + return getMixedValues(outputShapeInts, outputShapeValues, b); + } + + outputShapeInts.resize(expandedType.getRank(), ShapedType::kDynamic); + for (const auto &it : llvm::enumerate(reassociation)) { + ReassociationIndices indexGroup = it.value(); + + int64_t indexGroupStaticSizesProductInt = 1; + bool foundDynamicShape = false; + for (int64_t index : indexGroup) { + int64_t outputDimSize = expandedType.getDimSize(index); + // Cannot infer expanded shape with multiple dynamic dims in the + // same reassociation group! + if (ShapedType::isDynamic(outputDimSize)) { + if (foundDynamicShape) + return std::nullopt; + foundDynamicShape = true; + } else { + outputShapeInts[index] = outputDimSize; + indexGroupStaticSizesProductInt *= outputDimSize; + } + } + if (!foundDynamicShape) + continue; + + int64_t inputIndex = it.index(); + // Call get() under the assumption that we're not casting + // dynamism. + Value indexGroupSize = inputShape[inputIndex].get(); + Value indexGroupStaticSizesProduct = + b.create(loc, indexGroupStaticSizesProductInt); + Value dynamicDimSize = b.createOrFold( + loc, indexGroupSize, indexGroupStaticSizesProduct); + outputShapeValues.push_back(dynamicDimSize); + } + + if ((int64_t)outputShapeValues.size() != + llvm::count(outputShapeInts, ShapedType::kDynamic)) + return std::nullopt; + + return getMixedValues(outputShapeInts, outputShapeValues, b); +} + std::optional> mlir::getReassociationIndicesForReshape(ShapedType sourceType, ShapedType targetType) { @@ -168,7 +230,7 @@ ArrayAttr mlir::getReassociationIndicesAttribute( } SmallVector mlir::convertReassociationMapsToIndices( - OpBuilder &b, ArrayRef reassociationExprs) { + ArrayRef reassociationExprs) { SmallVector reassociationIndices; for (const auto &exprs : reassociationExprs) { ReassociationIndices indices; @@ -230,24 +292,17 @@ LogicalResult mlir::reshapeLikeShapesAreCompatible( ArrayRef reassociationMaps, bool isExpandingReshape) { unsigned expandedDimStart = 0; for (const auto &map : llvm::enumerate(reassociationMaps)) { - std::optional dynamicShape; + bool foundDynamicShape = false; int64_t linearizedStaticShape = 1; + for (const auto &dim : llvm::enumerate( expandedShape.slice(expandedDimStart, map.value().size()))) { - if (ShapedType::isDynamic(dim.value())) { - if (isExpandingReshape && dynamicShape) { - return emitError("invalid to have a single dimension (" + - Twine(map.index()) + - ") expanded into multiple dynamic dims (" + - Twine(expandedDimStart + dynamicShape.value()) + - "," + Twine(expandedDimStart + dim.index()) + ")"); - } - dynamicShape = dim.index(); - } else { + if (ShapedType::isDynamic(dim.value())) + foundDynamicShape = true; + else linearizedStaticShape *= dim.value(); - } } - if (dynamicShape) { + if (foundDynamicShape) { if (!ShapedType::isDynamic(collapsedShape[map.index()])) { return emitError( "expected dimension " + Twine(map.index()) + diff --git a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp index 1e8197e10944..74a53709592d 100644 --- a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp +++ b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp @@ -180,9 +180,8 @@ SmallVector getMixedValues(ArrayRef staticValues, /// Decompose a vector of mixed static or dynamic values into the corresponding /// pair of arrays. This is the inverse function of `getMixedValues`. -std::pair> -decomposeMixedValues(Builder &b, - const SmallVectorImpl &mixedValues) { +std::pair, SmallVector> +decomposeMixedValues(const SmallVectorImpl &mixedValues) { SmallVector staticValues; SmallVector dynamicValues; for (const auto &it : mixedValues) { @@ -193,7 +192,7 @@ decomposeMixedValues(Builder &b, dynamicValues.push_back(it.get()); } } - return {b.getI64ArrayAttr(staticValues), dynamicValues}; + return {staticValues, dynamicValues}; } /// Helper to sort `values` according to matching `keys`. diff --git a/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir index 87d613986c7c..b86103422b07 100644 --- a/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir +++ b/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir @@ -453,7 +453,7 @@ func.func @collapse_shape_dynamic_with_non_identity_layout( func.func @expand_shape_static(%arg0: memref<3x4x5xf32>) -> memref<1x3x4x1x5xf32> { // Reshapes that expand a contiguous tensor with some 1's. - %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] + %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] : memref<3x4x5xf32> into memref<1x3x4x1x5xf32> return %0 : memref<1x3x4x1x5xf32> } @@ -510,7 +510,7 @@ func.func @collapse_shape_fold_zero_dim(%arg0 : memref<1x1xf32>) -> memref // ----- func.func @expand_shape_zero_dim(%arg0 : memref) -> memref<1x1xf32> { - %0 = memref.expand_shape %arg0 [] : memref into memref<1x1xf32> + %0 = memref.expand_shape %arg0 [] output_shape [1, 1] : memref into memref<1x1xf32> return %0 : memref<1x1xf32> } @@ -571,13 +571,13 @@ func.func @collapse_shape_dynamic(%arg0 : memref<1x2x?xf32>) -> memref<1x?xf32> // ----- -func.func @expand_shape_dynamic(%arg0 : memref<1x?xf32>) -> memref<1x2x?xf32> { - %0 = memref.expand_shape %arg0 [[0], [1, 2]]: memref<1x?xf32> into memref<1x2x?xf32> +func.func @expand_shape_dynamic(%arg0 : memref<1x?xf32>, %sz0: index) -> memref<1x2x?xf32> { + %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [1, 2, %sz0]: memref<1x?xf32> into memref<1x2x?xf32> return %0 : memref<1x2x?xf32> } // CHECK-LABEL: func.func @expand_shape_dynamic( -// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32>) -> memref<1x2x?xf32> { +// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32>, %[[SZ0:.*]]: index) -> memref<1x2x?xf32> { // CHECK: %[[MEM:.*]] = builtin.unrealized_conversion_cast %[[ARG]] : memref<1x?xf32> to !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_BUFFER:.*]] = llvm.extractvalue %[[MEM]][0] : !llvm.struct<(ptr, ptr, i64, // CHECK: %[[ALIGNED_BUFFER:.*]] = llvm.extractvalue %[[MEM]][1] : !llvm.struct<(ptr, ptr, i64, @@ -614,15 +614,15 @@ func.func @expand_shape_dynamic(%arg0 : memref<1x?xf32>) -> memref<1x2x?xf32> { // ----- func.func @expand_shape_dynamic_with_non_identity_layout( - %arg0 : memref<1x?xf32, strided<[?, ?], offset: ?>>) -> + %arg0 : memref<1x?xf32, strided<[?, ?], offset: ?>>, %sz0: index) -> memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> { - %0 = memref.expand_shape %arg0 [[0], [1, 2]]: + %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [1, 2, %sz0] : memref<1x?xf32, strided<[?, ?], offset: ?>> into memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> return %0 : memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> } // CHECK-LABEL: func.func @expand_shape_dynamic_with_non_identity_layout( -// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32, strided<[?, ?], offset: ?>>) -> memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> { +// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32, strided<[?, ?], offset: ?>>, %[[SZ0:.*]]: index) -> memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> { // CHECK: %[[MEM:.*]] = builtin.unrealized_conversion_cast %[[ARG]] : memref<1x?xf32, strided<[?, ?], offset: ?>> to !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_BUFFER:.*]] = llvm.extractvalue %[[MEM]][0] : !llvm.struct<(ptr, ptr, i64, // CHECK: %[[ALIGNED_BUFFER:.*]] = llvm.extractvalue %[[MEM]][1] : !llvm.struct<(ptr, ptr, i64, diff --git a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir index 37999d6fc14a..baf9cfe610a5 100644 --- a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir +++ b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir @@ -334,9 +334,9 @@ memref.global "private" @gv4 : memref = dense<1.0> {alignment = 64} // CHECK-LABEL: func @expand_shape_static( // CHECK-SAME: %[[ARG:.*]]: memref<{{.*}}>) func.func @expand_shape_static(%arg0: memref<3x4x5xf32>) -> memref<1x3x4x1x5xf32> { - // CHECK: memref.expand_shape %[[ARG]] {{\[}}[0, 1], [2], [3, 4]] + // CHECK: memref.expand_shape %[[ARG]] {{\[}}[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] // Reshapes that expand a contiguous tensor with some 1's. - %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] + %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] : memref<3x4x5xf32> into memref<1x3x4x1x5xf32> return %0 : memref<1x3x4x1x5xf32> } diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir index 3ec15221e299..03c9fec1c9a8 100644 --- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir @@ -348,7 +348,7 @@ func.func @test_add_2d_all_dynamic(%arg0: tensor, %arg1: tensor, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { - // CHECK: %[[ARG0_EXPANDED:.*]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2]] : tensor<3x4xf32> into tensor<1x3x4xf32> + // CHECK: %[[ARG0_EXPANDED:.*]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2]] output_shape [1, 3, 4] : tensor<3x4xf32> into tensor<1x3x4xf32> // CHECK: %[[VAL_0:.*]] = tensor.empty() : tensor<2x3x4xf32> // CHECK: %[[RESULT:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP1]]], iterator_types = ["parallel", "parallel", "parallel"]} ins(%[[ARG0_EXPANDED]], %[[ARG1]] : tensor<1x3x4xf32>, tensor<2x3x4xf32>) outs(%[[VAL_0]] : tensor<2x3x4xf32>) { // CHECK: ^bb0(%[[VAL_1:.*]]: f32, %[[VAL_2:.*]]: f32, %[[VAL_3:.*]]: f32): @@ -871,7 +871,7 @@ func.func @reduce_float(%arg0: tensor<5x4xf32>) -> () { // CHECK: [[RES:%.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield [[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<4xf32> into tensor<1x4xf32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [1, 4] : tensor<4xf32> into tensor<1x4xf32> %0 = tosa.reduce_sum %arg0 {axis = 0 : i32} : (tensor<5x4xf32>) -> tensor<1x4xf32> // CHECK: [[INIT:%.+]] = tensor.empty() : tensor<5xf32> @@ -882,7 +882,7 @@ func.func @reduce_float(%arg0: tensor<5x4xf32>) -> () { // CHECK: [[RES:%.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield [[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<5xf32> into tensor<5x1xf32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [5, 1] : tensor<5xf32> into tensor<5x1xf32> %1 = tosa.reduce_sum %arg0 {axis = 1 : i32} : (tensor<5x4xf32>) -> tensor<5x1xf32> // CHECK: arith.constant 1.0 @@ -920,7 +920,10 @@ func.func @reduce_float_dyn(%arg0: tensor) -> () { // CHECK: %[[RES:.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] : tensor into tensor + // CHECK: %[[C0_0:.+]] = arith.constant 0 : index + // CHECK: %[[DIM_1:.+]] = tensor.dim %[[REDUCE]], %[[C0_0]] : tensor + // CHECK: %[[C1:.+]] = arith.constant 1 : index + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] output_shape [%[[DIM_1]], 1, 4] : tensor into tensor %0 = tosa.reduce_sum %arg0 {axis = 1 : i32} : (tensor) -> tensor return } @@ -938,7 +941,7 @@ func.func @reduce_float_dyn_rank_1(%arg0: tensor) -> () { // CHECK: %[[RES:.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}] : tensor into tensor<1xf32> + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}] output_shape [1] : tensor into tensor<1xf32> %0 = tosa.reduce_sum %arg0 {axis = 0 : i32} : (tensor) -> tensor<1xf32> return } @@ -958,7 +961,10 @@ func.func @reduce_float_dyn_nonzero_batch(%arg0: tensor<5x?x4xf32>) -> () { // CHECK: %[[RES:.+]] = arith.mulf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] : tensor<5x?xf32> into tensor<5x?x1xf32> + // CHECK: %[[C1_0:.+]] = arith.constant 1 : index + // CHECK: %[[DIM_1:.+]] = tensor.dim %[[REDUCE]], %[[C1_0]] : tensor<5x?xf32> + // CHECK: %[[C1_2:.+]] = arith.constant 1 : index + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] output_shape [5, %[[DIM_1]], 1] : tensor<5x?xf32> into tensor<5x?x1xf32> %0 = tosa.reduce_prod %arg0 {axis = 2 : i32} : (tensor<5x?x4xf32>) -> tensor<5x?x1xf32> return } @@ -978,7 +984,10 @@ func.func @reduce_float_dyn_multiple(%arg0: tensor) -> () { // CHECK: %[[MAX:.+]] = arith.maximumf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[MAX]] : f32 // CHECK: } - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0, 1]] : tensor into tensor + // CHECK: %[[C0_0:.+]] = arith.constant 0 : index + // CHECK: %[[DIM_1:.+]] = tensor.dim %[[REDUCE]], %[[C0_0]] : tensor + // CHECK: %[[C1_2:.+]] = arith.constant 1 : index + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0, 1]] output_shape [%[[DIM_1]], 1] : tensor into tensor %0 = tosa.reduce_max %arg0 {axis = 1 : i32} : (tensor) -> tensor return } @@ -996,7 +1005,7 @@ func.func @reduce_int(%arg0: tensor<5x4xi32>) -> () { // CHECK: [[RES:%.+]] = arith.addi %[[ARG1]], %[[ARG2]] : i32 // CHECK: linalg.yield [[RES]] : i32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<4xi32> into tensor<1x4xi32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [1, 4] : tensor<4xi32> into tensor<1x4xi32> %0 = tosa.reduce_sum %arg0 {axis = 0 : i32} : (tensor<5x4xi32>) -> tensor<1x4xi32> // CHECK: [[INIT:%.+]] = tensor.empty() @@ -1007,7 +1016,7 @@ func.func @reduce_int(%arg0: tensor<5x4xi32>) -> () { // CHECK: [[RES:%.+]] = arith.addi %[[ARG1]], %[[ARG2]] : i32 // CHECK: linalg.yield [[RES]] : i32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<5xi32> into tensor<5x1xi32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [5, 1] : tensor<5xi32> into tensor<5x1xi32> %1 = tosa.reduce_sum %arg0 {axis = 1 : i32} : (tensor<5x4xi32>) -> tensor<5x1xi32> // CHECK: arith.constant 1 @@ -1043,7 +1052,7 @@ func.func @reduce_bool(%arg0: tensor<5x4xi1>) -> () { // CHECK: [[RES:%.+]] = arith.andi %[[ARG1]], %[[ARG2]] : i1 // CHECK: linalg.yield [[RES]] : i1 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<4xi1> into tensor<1x4xi1> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [1, 4] : tensor<4xi1> into tensor<1x4xi1> %0 = tosa.reduce_all %arg0 {axis = 0 : i32} : (tensor<5x4xi1>) -> tensor<1x4xi1> // CHECK: arith.constant false diff --git a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir index a8a3c42e1684..b8c3d56f21f1 100644 --- a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir +++ b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir @@ -14,7 +14,7 @@ func.func @test_reshape_0d_same_s2s_explicit(%arg0: tensor) -> tensor // CHECK-LABEL: test_reshape_0d_up_s2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> // CHECK: %[[VAL_1:.*]] = tensor.cast %[[VAL_0]] : tensor<1xf32> to tensor // CHECK: return %[[VAL_1]] : tensor func.func @test_reshape_0d_up_s2d_auto(%arg0: tensor) -> tensor { @@ -26,7 +26,7 @@ func.func @test_reshape_0d_up_s2d_auto(%arg0: tensor) -> tensor { // CHECK-LABEL: test_reshape_0d_up_s2d_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> // CHECK: %[[VAL_1:.*]] = tensor.cast %[[VAL_0]] : tensor<1xf32> to tensor // CHECK: return %[[VAL_1]] : tensor func.func @test_reshape_0d_up_s2d_explicit(%arg0: tensor) -> tensor { @@ -38,7 +38,7 @@ func.func @test_reshape_0d_up_s2d_explicit(%arg0: tensor) -> tensor // CHECK-LABEL: test_reshape_0d_up_s2s_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> // CHECK: return %[[VAL_0]] : tensor<1xf32> func.func @test_reshape_0d_up_s2s_auto(%arg0: tensor) -> tensor<1xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<1xf32> @@ -49,7 +49,7 @@ func.func @test_reshape_0d_up_s2s_auto(%arg0: tensor) -> tensor<1xf32> { // CHECK-LABEL: test_reshape_0d_up_s2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> // CHECK: return %[[VAL_0]] : tensor<1xf32> func.func @test_reshape_0d_up_s2s_explicit(%arg0: tensor) -> tensor<1xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<1xf32> @@ -83,8 +83,12 @@ func.func @test_reshape_1d_down_s2s_explicit(%arg0: tensor<1xf32>) -> tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor into tensor<2x?xf32> -// CHECK: return %[[VAL_0]] : tensor<2x?xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %arg0, %[[C0]] : tensor +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C2]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] output_shape [2, %[[VAL_0]]] : tensor into tensor<2x?xf32> +// CHECK: return %[[EXPANDED]] : tensor<2x?xf32> func.func @test_reshape_1d_up_d2d_auto(%arg0: tensor) -> tensor<2x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x?xf32> return %0 : tensor<2x?xf32> @@ -94,7 +98,7 @@ func.func @test_reshape_1d_up_d2d_auto(%arg0: tensor) -> tensor<2x?xf32> // CHECK-LABEL: test_reshape_1d_up_s2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<6xf32> -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<6xf32> into tensor<2x3xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] output_shape [2, 3] : tensor<6xf32> into tensor<2x3xf32> // CHECK: return %[[VAL_0]] : tensor<2x3xf32> func.func @test_reshape_1d_up_s2s_explicit(%arg0: tensor<6xf32>) -> tensor<2x3xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<6xf32>) -> tensor<2x3xf32> @@ -128,8 +132,12 @@ func.func @test_reshape_2d_down_s2s_explicit(%arg0: tensor<2x3xf32>) -> tensor<6 // CHECK-LABEL: test_reshape_2d_same_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor into tensor<2x?xf32> -// CHECK: return %[[VAL_1]] : tensor<2x?xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C2]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [2, %[[DIV]]] : tensor into tensor<2x?xf32> +// CHECK: return %[[EXPANDED]] : tensor<2x?xf32> func.func @test_reshape_2d_same_d2d_auto(%arg0: tensor) -> tensor<2x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x?xf32> return %0 : tensor<2x?xf32> @@ -140,7 +148,7 @@ func.func @test_reshape_2d_same_d2d_auto(%arg0: tensor) -> tensor<2x?xf // CHECK-LABEL: test_reshape_2d_same_s2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x4xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x4xf32> into tensor<8xf32> -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<8xf32> into tensor<4x2xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [4, 2] : tensor<8xf32> into tensor<4x2xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<4x2xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_2d_same_s2d_auto(%arg0: tensor<2x4xf32>) -> tensor { @@ -153,7 +161,7 @@ func.func @test_reshape_2d_same_s2d_auto(%arg0: tensor<2x4xf32>) -> tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x4xf32> into tensor<8xf32> -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<8xf32> into tensor<4x2xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [4, 2] : tensor<8xf32> into tensor<4x2xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<4x2xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_2d_same_s2d_explicit(%arg0: tensor<2x4xf32>) -> tensor { @@ -166,7 +174,7 @@ func.func @test_reshape_2d_same_s2d_explicit(%arg0: tensor<2x4xf32>) -> tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<3x2xf32> into tensor<6xf32> -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<6xf32> into tensor<2x3xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [2, 3] : tensor<6xf32> into tensor<2x3xf32> // CHECK: return %[[VAL_1]] : tensor<2x3xf32> func.func @test_reshape_2d_same_s2s_explicit(%arg0: tensor<3x2xf32>) -> tensor<2x3xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<3x2xf32>) -> tensor<2x3xf32> @@ -178,7 +186,11 @@ func.func @test_reshape_2d_same_s2s_explicit(%arg0: tensor<3x2xf32>) -> tensor<2 // CHECK-LABEL: test_reshape_3d_same_d2d_auto_empty // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2x?xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<3x2x?xf32> into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<0x3x?xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C0_0:.*]] = arith.constant 0 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C0_0]] : index +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [0, 3, %[[DIV]]] : tensor into tensor<0x3x?xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<0x3x?xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_auto_empty(%arg0: tensor<3x2x?xf32>) -> tensor { @@ -191,7 +203,11 @@ func.func @test_reshape_3d_same_d2d_auto_empty(%arg0: tensor<3x2x?xf32>) -> tens // CHECK-LABEL: test_reshape_3d_same_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x?x?xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<2x?x?xf32> into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<2x?x4xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C8:.*]] = arith.constant 8 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C8]] : index +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [2, %[[DIV]], 4] : tensor into tensor<2x?x4xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<2x?x4xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_auto(%arg0: tensor<2x?x?xf32>) -> tensor { @@ -204,7 +220,11 @@ func.func @test_reshape_3d_same_d2d_auto(%arg0: tensor<2x?x?xf32>) -> tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<2x3x?xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C6:.*]] = arith.constant 6 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C6]] : index +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [2, 3, %[[DIV]]] : tensor into tensor<2x3x?xf32> // CHECK: return %[[VAL_1]] : tensor<2x3x?xf32> func.func @test_reshape_3d_same_d2d_auto_identity(%arg0: tensor) -> tensor<2x3x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x3x?xf32> @@ -216,8 +236,12 @@ func.func @test_reshape_3d_same_d2d_auto_identity(%arg0: tensor) -> t // CHECK-LABEL: test_reshape_3d_same_d2d_explicit_empty // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2x?xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<3x2x?xf32> into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C6:.*]] = arith.constant 6 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C6]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [%[[DIV]], 3, 2] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_explicit_empty(%arg0: tensor<3x2x?xf32>) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<3x2x?xf32>) -> tensor @@ -229,8 +253,12 @@ func.func @test_reshape_3d_same_d2d_explicit_empty(%arg0: tensor<3x2x?xf32>) -> // CHECK-LABEL: test_reshape_3d_same_d2d_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C12:.*]] = arith.constant 12 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C12]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [%[[DIV]], 3, 4] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_explicit(%arg0: tensor) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor @@ -253,8 +281,12 @@ func.func @test_reshape_3d_same_d2d_explicit_identity(%arg0: tensor) // CHECK-LABEL: test_reshape_3d_same_d2s_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<2x?x4xf32> -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<2x?x4xf32> to tensor<2x3x4xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C8:.*]] = arith.constant 8 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C8]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [2, %[[DIV]], 4] : tensor into tensor<2x?x4xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor<2x?x4xf32> to tensor<2x3x4xf32> // CHECK: return %[[VAL_2]] : tensor<2x3x4xf32> func.func @test_reshape_3d_same_d2s_auto(%arg0: tensor) -> tensor<2x3x4xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x3x4xf32> @@ -266,8 +298,12 @@ func.func @test_reshape_3d_same_d2s_auto(%arg0: tensor) -> tensor<2x3 // CHECK-LABEL: test_reshape_3d_same_d2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor<2x3x4xf32> +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor +// CHECK: %[[C12:.*]] = arith.constant 12 : index +// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C12]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [%[[DIV]], 3, 4] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor<2x3x4xf32> // CHECK: return %[[VAL_2]] : tensor<2x3x4xf32> func.func @test_reshape_3d_same_d2s_explicit(%arg0: tensor) -> tensor<2x3x4xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x3x4xf32> @@ -288,10 +324,14 @@ func.func @test_reshape_3d_same_s2s_explicit_identity(%arg0: tensor<2x3x4xf32>) // CHECK-LABEL: test_reshape_3d_up_d2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2, 3]] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor<1x3x2x1xf32> -// CHECK: return %[[VAL_2]] : tensor<1x3x2x1xf32> +// CHECK: %[[COLLAPSED:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[COLLAPSED]], %[[C0]] : tensor +// CHECK: %[[C6:.*]] = arith.constant 6 : index +// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C6]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[COLLAPSED]] {{\[\[}}0, 1, 2, 3]] output_shape [%[[VAL_0]], 3, 2, 1] : tensor into tensor +// CHECK: %[[CAST:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor<1x3x2x1xf32> +// CHECK: return %[[CAST]] : tensor<1x3x2x1xf32> func.func @test_reshape_3d_up_d2s_explicit(%input: tensor) -> tensor<1x3x2x1xf32> { %0 = tosa.reshape %input {new_shape = array} : (tensor) -> tensor<1x3x2x1xf32> return %0 : tensor<1x3x2x1xf32> @@ -313,9 +353,13 @@ func.func @test_reshape_4d_down_d2s_explicit(%arg0: tensor) -> tens // CHECK-LABEL: test_reshape_5d_down_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4]] : tensor into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: return %[[VAL_1]] : tensor +// CHECK: %[[COLLAPSED:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4]] : tensor into tensor +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[COLLAPSED]], %[[C0]] : tensor +// CHECK: %[[C6:.*]] = arith.constant 6 : index +// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C6]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[COLLAPSED]] {{\[\[}}0, 1, 2]] output_shape [%[[VAL_0]], 2, 3] : tensor into tensor +// CHECK: return %[[EXPANDED]] : tensor func.func @test_reshape_5d_down_d2d_auto(%arg0: tensor) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor return %0 : tensor @@ -325,9 +369,13 @@ func.func @test_reshape_5d_down_d2d_auto(%arg0: tensor) -> tensor // CHECK-LABEL: test_reshape_6d_down_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<1x2x?x5x7x11xf32> -// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4, 5]] : tensor<1x2x?x5x7x11xf32> into tensor -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: return %[[VAL_1]] : tensor +// CHECK: %[[COLLAPSED:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4, 5]] : tensor<1x2x?x5x7x11xf32> into tensor +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[DIM:.*]] = tensor.dim %[[COLLAPSED]], %[[C0]] : tensor +// CHECK: %[[C385:.*]] = arith.constant 385 : index +// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C385]] : index +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[COLLAPSED]] {{\[\[}}0, 1, 2]] output_shape [%[[VAL_0]], 5, 77] : tensor into tensor +// CHECK: return %[[EXPANDED]] : tensor func.func @test_reshape_6d_down_d2d_auto(%arg0: tensor<1x2x?x5x7x11xf32>) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<1x2x?x5x7x11xf32>) -> tensor return %0 : tensor diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir index 9a3e14b6d391..efe59af97d96 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir @@ -132,7 +132,7 @@ func.func @shape_mismatch(%t: tensor<5x6x128xf32>) -> tensor<5x6x128xf32> { %cst = arith.constant 8.0 : f32 %0 = tensor.empty() : tensor<128xf32> %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<128xf32>) -> tensor<128xf32> - %2 = tensor.expand_shape %1 [[0, 1, 2]] + %2 = tensor.expand_shape %1 [[0, 1, 2]] output_shape [1, 1, 128] : tensor<128xf32> into tensor<1x1x128xf32> %3 = tensor.insert_slice %2 into %t[2, 3, 0][1, 1, 128][1, 1, 1] : tensor<1x1x128xf32> into tensor<5x6x128xf32> diff --git a/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir b/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir index 0e353a1fa43f..4bf81820f0e8 100644 --- a/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir +++ b/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir @@ -165,7 +165,9 @@ func.func @rank_reducing_slice(%width : index) -> tensor<1x1x1x?xf32> { %init = tensor.empty(%width) : tensor<1x?xf32> %fill = linalg.fill ins(%cst : f32) outs(%init : tensor<1x?xf32>) -> tensor<1x?xf32> %slice = tensor.extract_slice %fill[0, 0] [1, %width] [1, 1] : tensor<1x?xf32> to tensor - %expand = tensor.expand_shape %slice [[0, 1, 2, 3]] : tensor into tensor<1x1x1x?xf32> + %c0 = arith.constant 0 : index + %sz0 = tensor.dim %slice, %c0 : tensor + %expand = tensor.expand_shape %slice [[0, 1, 2, 3]] output_shape [1, 1, 1, %sz0] : tensor into tensor<1x1x1x?xf32> return %expand : tensor<1x1x1x?xf32> } diff --git a/mlir/test/Dialect/Linalg/collapse-dim.mlir b/mlir/test/Dialect/Linalg/collapse-dim.mlir index 547320f53387..61bedecbdca5 100644 --- a/mlir/test/Dialect/Linalg/collapse-dim.mlir +++ b/mlir/test/Dialect/Linalg/collapse-dim.mlir @@ -52,7 +52,7 @@ func.func @collapse_parallel( // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]} // CHECK-SAME: ins(%[[S]] : tensor<32x2x40960xf32>) outs(%[[D]] : tensor<2x32x40960xf32>) { // CHECK: } -> tensor<2x32x40960xf32> -// CHECK: tensor.expand_shape %[[R]] {{\[}}[0], [1], [2, 3]] : tensor<2x32x40960xf32> into tensor<2x32x10x4096xf32> +// CHECK: tensor.expand_shape %[[R]] {{\[}}[0], [1], [2, 3]] output_shape [2, 32, 10, 4096] : tensor<2x32x40960xf32> into tensor<2x32x10x4096xf32> // ----- @@ -127,8 +127,8 @@ func.func @uncollapsable_strided_memref(%arg0: memref<2x6x24x48xi32>, %arg1: mem // CHECK: %[[VAL_4:.*]] = tensor.collapse_shape %[[VAL_2]] {{\[\[}}0], [1], [2, 3]] : tensor<1x2x12x5xf32> into tensor<1x2x60xf32> // CHECK: %[[VAL_5:.*]] = tensor.collapse_shape %[[VAL_3]] {{\[\[}}0], [1], [2, 3]] : tensor<1x2x12x5xf32> into tensor<1x2x60xf32> // CHECK: %[[VAL_6:.*]] = linalg.copy ins(%[[VAL_4]] : tensor<1x2x60xf32>) outs(%[[VAL_5]] : tensor<1x2x60xf32>) -> tensor<1x2x60xf32> -// CHECK: %[[VAL_7:.*]] = tensor.expand_shape %[[VAL_6]] {{\[\[}}0], [1], [2, 3]] : tensor<1x2x60xf32> into tensor<1x2x12x5xf32> -// CHECK: %[[VAL_8:.*]] = tensor.expand_shape %[[VAL_7]] {{\[\[}}0], [1], [2, 3], [4]] : tensor<1x2x12x5xf32> into tensor<1x2x3x4x5xf32, 3 : i64> +// CHECK: %[[VAL_7:.*]] = tensor.expand_shape %[[VAL_6]] {{\[\[}}0], [1], [2, 3]] output_shape [1, 2, 12, 5] : tensor<1x2x60xf32> into tensor<1x2x12x5xf32> +// CHECK: %[[VAL_8:.*]] = tensor.expand_shape %[[VAL_7]] {{\[\[}}0], [1], [2, 3], [4]] output_shape [1, 2, 3, 4, 5] : tensor<1x2x12x5xf32> into tensor<1x2x3x4x5xf32, 3 : i64> // CHECK: return %[[VAL_8]] : tensor<1x2x3x4x5xf32, 3 : i64> // CHECK: } diff --git a/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir b/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir index a64319963531..c7c846d7ecc9 100644 --- a/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir +++ b/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir @@ -50,7 +50,7 @@ module attributes {transform.with_named_sequence} { // CHECK: linalg.yield %[[EXTRACTED_INPUT]] : f32 // CHECK: IR printer: transformed -// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d3)> @@ -78,7 +78,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<1x196x16xf32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK: return %[[RESULT]] func.func @conv_16433136(%arg0: tensor<1x16x16x4xf32>, %arg1: tensor<3x3x4x16xf32>, %arg2: tensor<1x14x14x16xf32>) -> tensor<1x14x14x16xf32> { @@ -204,7 +204,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<8x196x16xf32> -// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1, 2], [3]] : tensor<8x196x16xf32> into tensor<8x14x14x16xf32> +// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1, 2], [3]] output_shape [8, 14, 14, 16] : tensor<8x196x16xf32> into tensor<8x14x14x16xf32> // CHECK: return %[[CS_FINAL]] func.func @batch_nhwc_conv(%arg0: tensor<8x16x16x4xf32>, %arg1: tensor<3x3x4x16xf32>, %arg2: tensor<8x14x14x16xf32>) -> tensor<8x14x14x16xf32> { %0 = linalg.conv_2d_nhwc_hwcf @@ -269,7 +269,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<8x16x196xf32> -// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1], [2, 3]] : tensor<8x16x196xf32> into tensor<8x16x14x14xf32> +// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1], [2, 3]] output_shape [8, 16, 14, 14] : tensor<8x16x196xf32> into tensor<8x16x14x14xf32> // CHECK: return %[[CS_FINAL]] func.func @batch_nchw_conv(%arg0: tensor<8x4x16x16xf32>, %arg1: tensor<16x4x3x3xf32>, %arg2: tensor<8x16x14x14xf32>) -> tensor<8x16x14x14xf32> { %0 = linalg.conv_2d_nchw_fchw @@ -310,7 +310,7 @@ module attributes {transform.with_named_sequence} { // CHECK: linalg.yield %[[EXTRACTED_INPUT]] : f32 // CHECK: IR printer: transformed -// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d3)> @@ -338,7 +338,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<1x196x16xf32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK: return %[[RESULT]] func.func @conv_2d_nhwc_fhwc(%arg0: tensor<1x16x16x4xf32>, %arg1: tensor<16x3x3x4xf32>, %arg2: tensor<1x14x14x16xf32>) -> tensor<1x14x14x16xf32> { @@ -378,7 +378,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addi %[[MUL]], %[[ARG2]] : i32 // CHECK: linalg.yield %[[ADD]] : i32 // CHECK: } -> tensor<1x196x16xi32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xi32> into tensor<1x14x14x16xi32> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xi32> into tensor<1x14x14x16xi32> // CHECK: return %[[RESULT]] func.func @conv_integer_extend(%arg0: tensor<1x16x16x4xi8>, %arg1: tensor<3x3x4x16xi8>, %arg2: tensor<1x14x14x16xi32>) -> tensor<1x14x14x16xi32> { @@ -416,7 +416,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = complex.add %[[MUL]], %[[ARG2]] : complex // CHECK: linalg.yield %[[ADD]] : complex // CHECK: } -> tensor<1x196x16xcomplex> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> // CHECK: return %[[RESULT]] func.func @conv_complex(%arg0: tensor<1x16x16x4xcomplex>, %arg1: tensor<3x3x4x16xcomplex>, %arg2: tensor<1x14x14x16xcomplex>) -> tensor<1x14x14x16xcomplex> { @@ -459,7 +459,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = complex.add %[[MUL]], %[[ARG2]] : complex // CHECK: linalg.yield %[[ADD]] : complex // CHECK: } -> tensor<1x196x16xcomplex> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> // CHECK: return %[[RESULT]] func.func @conv_complex_extended(%arg0: tensor<1x16x16x4xcomplex>, %arg1: tensor<3x3x4x16xcomplex>, %arg2: tensor<1x14x14x16xcomplex>) -> tensor<1x14x14x16xcomplex> { @@ -500,7 +500,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = complex.add %[[MUL]], %[[ARG2]] : complex // CHECK: linalg.yield %[[ADD]] : complex // CHECK: } -> tensor<1x196x16xcomplex> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> // CHECK: return %[[RESULT]] func.func @conv_complex_f16_extended(%arg0: tensor<1x16x16x4xcomplex>, %arg1: tensor<3x3x4x16xf16>, %arg2: tensor<1x14x14x16xcomplex>) -> tensor<1x14x14x16xcomplex> { diff --git a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir index 79d61ab757e3..bee08503298f 100644 --- a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir +++ b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir @@ -988,17 +988,20 @@ func.func @no_bubble_up_pack_through_non_divisible_collapse(%1: tensor<3072x64x4 // ----- -func.func @push_down_unpack_through_expand(%5: tensor, %dim: index) -> tensor { +func.func @push_down_unpack_through_expand(%5: tensor, %dim: index, %sz0: 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 + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] output_shape [%sz0, 256, 256] : 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: %[[C32:.+]] = arith.constant 32 : index // CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3], [4]] : tensor into tensor +// CHECK: %[[DIM0:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[SZ0:.+]] = arith.divui %[[DIM0]], %[[C32]] : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3], [4]] output_shape [%[[SZ0]], 32, 32, 8, 8] : 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 @@ -1009,12 +1012,12 @@ func.func @push_down_unpack_through_expand(%5: tensor, %dim: index 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> + %expanded = tensor.expand_shape %unpack [[0], [1, 2], [3]] output_shape [4, 12, 256, 256] : 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: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1], [2, 3], [4], [5]] output_shape [4, 32, 12, 32, 8, 8] : 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> @@ -1024,29 +1027,32 @@ func.func @push_down_permuted_unpack_through_expand(%5: tensor<4x32x384x8x8xf32> 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> + %expanded = tensor.expand_shape %unpack [[0, 1, 2], [3]] output_shape [3, 16, 1, 256] : 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: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3], [4], [5]] output_shape [3, 2, 1, 32, 8, 8] : 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 { +func.func @push_down_unpack_through_expand_on_outer_dims(%5: tensor, %dim: index, %sz0: 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 + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] output_shape [%sz0, 256, 256] : 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: %[[C256:.+]] = arith.constant 256 : index // CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3]] : tensor into tensor +// CHECK: %[[DIM0:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[SZ0:.+]] = arith.divui %[[DIM0]], %[[C256]] : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3]] output_shape [%[[SZ0]], 256, 32, 8] : 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 @@ -1057,11 +1063,11 @@ func.func @push_down_unpack_through_expand_on_outer_dims(%5: 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> + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] output_shape [256, 12, 256] : 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: %[[EXPANDED:.+]] = tensor.expand_shape %[[UNPACK]] {{\[}}[0, 1], [2]] output_shape [256, 12, 256] : tensor<3072x256xf32> into tensor<256x12x256xf32> // CHECK: return %[[EXPANDED]] : tensor<256x12x256xf32> diff --git a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir index c140b6abcc37..a9cbaaf7fdc4 100644 --- a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir +++ b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir @@ -25,13 +25,22 @@ func.func @drop_one_trip_loops(%arg0 : tensor, %arg1 : f32, %shape: t // CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1, d2) -> (d0, d2)> // CHECK-DAG: #[[$MAP2:.*]] = affine_map<(d0, d1, d2) -> ()> // CHECK-DAG: #[[$MAP3:.*]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> +// CHECK-DAG: #[[$MAP4:.*]] = affine_map<()[s0, s1] -> (s0 * s1)> // CHECK-LABEL: func @drop_one_trip_loops -// CHECK: tensor.collapse_shape %{{.*}} {{\[}}[0, 1], [2]] -// CHECK: tensor.collapse_shape %{{.*}} {{\[}}[0, 1], [2, 3], [4]] +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: tensor.collapse_shape %{{.*}} {{\[\[}}0, 1], [2]] +// CHECK: tensor.collapse_shape %{{.*}} {{\[\[}}0, 1], [2, 3], [4]] // CHECK: linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP1]], #[[$MAP2]], #[[$MAP3]]] // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"] -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2, 3], [4]] +// CHECK: %[[DIM:.*]] = tensor.dim %{{.*}}, %[[C0]] +// CHECK: %[[VAL_1:.*]] = affine.apply #[[$MAP4]]()[%[[DIM]], %[[C1]]] +// CHECK: %[[DIM_1:.*]] = tensor.dim %{{.*}}, %[[C2]] +// CHECK: %[[VAL_2:.*]] = affine.apply #[[$MAP4]]()[%[[DIM_1]], %[[C1]]] +// CHECK: %[[DIM_2:.*]] = tensor.dim %{{.*}}, %[[C2]] +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %{{.*}} {{\[\[}}0, 1], [2, 3], [4]] output_shape [%[[VAL_1]], 1, %[[VAL_2]], 1, %[[DIM_2]]] : tensor into tensor // CHECK-SLICES-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1, d2) -> (d0, d2)> // CHECK-SLICES-DAG: #[[$MAP2:.*]] = affine_map<(d0, d1, d2) -> ()> @@ -70,13 +79,18 @@ func.func @drop_one_trip_loops_all_ones(%arg0 : tensor<1x1x1xf32>, %arg1 : f32, } // CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0) -> ()> // CHECK-DAG: #[[$MAP2:.*]] = affine_map<(d0) -> (d0)> +// CHECK-DAG: #[[$MAP3:.*]] = affine_map<()[s0, s1, s2, s3, s4] -> ((((s0 * s1) * s2) * s3) * s4)> // CHECK-LABEL: func @drop_one_trip_loops_all_ones +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[C1:.*]] = arith.constant 1 : index // CHECK: tensor.collapse_shape %{{.*}} [] // CHECK: tensor.collapse_shape %{{.*}} {{\[}}[0, 1, 2, 3, 4]] // CHECK: linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP1]], #[[$MAP1]], #[[$MAP2]]] // CHECK-SAME: iterator_types = ["parallel"] -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2, 3, 4]] +// CHECK: %[[DIM:.*]] = tensor.dim %{{.*}}, %[[C2]] : tensor<1x1x?x1x1xf32> +// CHECK: %[[SZ:.*]] = affine.apply #[[$MAP3]]()[%[[C1]], %[[C1]], %[[DIM]], %[[C1]], %[[C1]]] +// CHECK: %[[EXPAND:.*]] = tensor.expand_shape %{{.*}} {{\[\[}}0, 1, 2, 3, 4]] output_shape [1, 1, %[[SZ]], 1, 1] : tensor into tensor<1x1x?x1x1xf32> // ----- @@ -232,8 +246,8 @@ func.func @leading_dim_1_canonicalization(%arg0: tensor<1x5xf32>, %shape: tensor func.func @broadcast_test(%arg0 : tensor<5xf32>, %arg1 : tensor<5xf32>, %shape : tensor<5x5xf32>) -> tensor<5x5xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1]] : tensor<5xf32> into tensor<1x5xf32> - %1 = tensor.expand_shape %arg1 [[0, 1]] : tensor<5xf32> into tensor<5x1xf32> + %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [1, 5] : tensor<5xf32> into tensor<1x5xf32> + %1 = tensor.expand_shape %arg1 [[0, 1]] output_shape [5, 1] : tensor<5xf32> into tensor<5x1xf32> %2 = linalg.generic #trait ins(%0, %1 : tensor<1x5xf32>, tensor<5x1xf32>) outs(%shape : tensor<5x5xf32>) { @@ -331,7 +345,6 @@ func.func @fold_unit_dim_for_empty_tensor(%input: tensor<1x1000xf32>) -> tensor< // CHECK: func @fold_unit_dim_for_empty_tensor - // CHECK: %[[INPUT_RESHAPE:.+]] = tensor.collapse_shape %{{.+}} {{\[}}[0, 1]] : tensor<1x1000xf32> into tensor<1000xf32> // CHECK: %[[INIT:.+]] = tensor.empty() : tensor // CHECK: %[[FILL:.+]] = linalg.fill ins(%cst : f32) outs(%[[INIT]] : tensor) -> tensor @@ -340,7 +353,7 @@ func.func @fold_unit_dim_for_empty_tensor(%input: tensor<1x1000xf32>) -> tensor< // CHECK-SAME: iterator_types = ["reduction"] // CHECK-SAME: ins(%[[INPUT_RESHAPE]] : tensor<1000xf32>) // CHECK-SAME: outs(%[[FILL]] : tensor) -// CHECK: %[[GENERIC_RESHAPE:.+]] = tensor.expand_shape %[[GENERIC]] [] : tensor into tensor<1xf32> +// CHECK: %[[GENERIC_RESHAPE:.+]] = tensor.expand_shape %[[GENERIC]] [] output_shape [1] : tensor into tensor<1xf32> // CHECK: return %[[GENERIC_RESHAPE:.+]] : tensor<1xf32> @@ -364,11 +377,11 @@ func.func @fold_slice( // CHECK: %[[SLICE1:.+]] = tensor.extract_slice %[[ARG0]] // CHECK-SAME: to tensor // CHECK: %[[RESULT1:.+]] = tensor.expand_shape %[[SLICE1]] -// CHECK-SAME: [0, 1], [2], [3, 4, 5, 6] +// CHECK-SAME: {{\[\[}}0, 1], [2], [3, 4, 5, 6]] output_shape [1, %arg5, %arg6, 1, %arg7, 1, 1] : tensor into tensor<1x?x?x1x?x1x1xf32> // CHECK: %[[SLICE2:.+]] = tensor.extract_slice %[[ARG1]] // CHECK-SAME: to tensor // CHECK: %[[RESULT2:.+]] = tensor.expand_shape %[[SLICE2]] -// CHECK-SAME: [0, 1], [2], [3, 4, 5, 6] +// CHECK-SAME: {{\[\[}}0, 1], [2], [3, 4, 5, 6]] output_shape [1, %arg5, %arg6, 1, %arg7, 1, 1] : tensor into tensor<1x?x?x1x?x1x1xf32> // CHECK: return %[[RESULT1]], %[[RESULT2]] // ----- @@ -391,20 +404,27 @@ func.func @unit_dim_for_reduction(%arg0: tensor<1x?x1x?xf32>) -> tensor<1x?xf32> } -> tensor<1x?xf32> return %3 : tensor<1x?xf32> } -// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0, d1)> -// CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d0)> +// CHECK-DAG: #[[MAP:.+]] = affine_map<(d0, d1) -> (d0, d1)> +// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0)> +// CHECK-DAG: #[[MAP3:.+]] = affine_map<()[s0, s1, s2] -> ((s0 * s1) * s2)> // CHECK: func @unit_dim_for_reduction // CHECK-SAME: %[[ARG0:.+]]: tensor<1x?x1x?xf32> -// CHECK-DAG: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] -// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor -// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] -// CHECK: %[[RESULT:.+]] = linalg.generic -// CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP3]]] +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[CST:.+]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[C3:.+]] = arith.constant 3 : index +// CHECK: %[[DIM:.+]] = tensor.dim %arg0, %[[C3]] : tensor<1x?x1x?xf32> +// CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] +// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor +// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] +// CHECK: %[[RESULT:.+]] = linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP2]]] // CHECK-SAME: iterator_types = ["parallel", "reduction"] // CHECK-SAME: ins(%[[RESHAPE]] : tensor) // CHECK-SAME: outs(%[[FILL]] : tensor) -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] -// CHECK: return %[[RESULT_RESHAPE]] +// CHECK: %[[DIM_0:.*]] = tensor.dim %[[ARG0]], %[[C1]] : tensor<1x?x1x?xf32> +// CHECK: %[[VAL_3:.*]] = affine.apply #[[$MAP3]]()[%[[C1]], %[[DIM_0]], %[[C1]]] +// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[GENERIC]] {{\[\[}}0, 1]] output_shape [1, %[[VAL_3]]] : tensor into tensor<1x?xf32> +// CHECK: return %[[EXPANDED]] : tensor<1x?xf32> // ----- @@ -437,7 +457,7 @@ func.func @unit_dim_for_both_reduction(%arg0: tensor<1x?x1x1xf32>) -> tensor<1x1 // CHECK-SAME: iterator_types = ["parallel"] // CHECK-SAME: ins(%[[RESHAPE]], %[[FILL]] : tensor, tensor<1xf32>) // CHECK-SAME: outs(%[[INIT2]] : tensor<1xf32>) -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] output_shape [1, 1] // CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -460,20 +480,28 @@ func.func @unit_dim_for_reduction_inner(%arg0: tensor) -> tensor tensor return %3 : tensor } -// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0, d1)> -// CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d0)> +// CHECK-DAG: #[[MAP:.+]] = affine_map<(d0, d1) -> (d0, d1)> +// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0)> +// CHECK-DAG: #[[MAP3:.+]] = affine_map<()[s0, s1] -> (s0 * s1)> // CHECK: func @unit_dim_for_reduction_inner // CHECK-SAME: %[[ARG0:.+]]: tensor -// CHECK-DAG: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]] -// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor -// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] -// CHECK: %[[RESULT:.+]] = linalg.generic -// CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP3]]] +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[CST:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[DIM:.*]] = tensor.dim %arg0, %[[C2]] : tensor +// CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]] +// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor +// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] +// CHECK: %[[RESULT:.+]] = linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP2]]] // CHECK-SAME: iterator_types = ["parallel", "reduction"] // CHECK-SAME: ins(%[[RESHAPE]] : tensor) // CHECK-SAME: outs(%[[FILL]] : tensor) -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] -// CHECK: return %[[RESULT_RESHAPE]] +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[VAL_3:.+]] = affine.apply #[[$MAP3]]()[%[[DIM_0]], %[[C1]]] +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] output_shape [%[[VAL_3]], 1] : tensor into tensor +// CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -484,7 +512,7 @@ func.func @slice_unit_dims(%arg0: tensor<1x3xf32>) -> tensor<1x1xf32> { // CHECK-LABEL: func @slice_unit_dims // CHECK: %[[SLICE:.+]] = tensor.extract_slice // CHECK-SAME: tensor<1x3xf32> to tensor -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] [] +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] [] output_shape [1, 1] // CHECK: return %[[RESULT]] // ----- @@ -496,7 +524,7 @@ func.func @rank_reduced_extract_slice(%arg0: tensor<1x1x3x1x3xf32>) -> tensor<1x // CHECK-LABEL: func @rank_reduced_extract_slice // CHECK: %[[SLICE:.+]] = tensor.extract_slice // CHECK-SAME: tensor<1x1x3x1x3xf32> to tensor<3x3xf32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] {{\[}}[0, 1], [2]] +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] {{\[}}[0, 1], [2]] output_shape [1, 3, 3] // CHECK: return %[[RESULT]] // ----- @@ -709,8 +737,8 @@ func.func @leading_dim_1_canonicalization(%arg0: memref<1x5xf32>, %shape: memref func.func @broadcast_test(%arg0 : memref<5xf32>, %arg1 : memref<5xf32>, %shape : memref<5x5xf32>) -> memref<5x5xf32> { - %0 = memref.expand_shape %arg0 [[0, 1]] : memref<5xf32> into memref<1x5xf32> - %1 = memref.expand_shape %arg1 [[0, 1]] : memref<5xf32> into memref<5x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1]] output_shape [1, 5] : memref<5xf32> into memref<1x5xf32> + %1 = memref.expand_shape %arg1 [[0, 1]] output_shape [5, 1] : memref<5xf32> into memref<5x1xf32> linalg.generic #trait ins(%0, %1 : memref<1x5xf32>, memref<5x1xf32>) outs(%shape : memref<5x5xf32>) { @@ -966,7 +994,7 @@ func.func @drop_unit_pad_dims(%arg0: tensor<1x1x3x1x1xf32>) -> tensor<1x2x3x1x3x // CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0, 0] high[0, 0, 2] // CHECK: } : tensor<1x3x1xf32> to tensor<2x3x3xf32> // CHECK: tensor.expand_shape %[[PADDED]] -// CHECK-SAME: {{\[}}[0, 1], [2, 3], [4]{{\]}} : tensor<2x3x3xf32> into tensor<1x2x3x1x3xf32> +// CHECK-SAME: {{\[}}[0, 1], [2, 3], [4]{{\]}} output_shape [1, 2, 3, 1, 3] : tensor<2x3x3xf32> into tensor<1x2x3x1x3xf32> // CHECK-SLICES-LABEL: func @drop_unit_pad_dims // CHECK-SLICES: %[[EXTRACT:.+]] = tensor.extract_slice @@ -989,13 +1017,19 @@ func.func @drop_unit_pad_dynamic_dims(%arg0: tensor<1x?xf32>) -> tensor<1x?xf32> return %0 : tensor<1x?xf32> } +// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 * s1)> +// CHECK-DAG: #[[$MAP1:.+]] = affine_map<()[s0] -> (s0 + 11)> // CHECK-LABEL: func @drop_unit_pad_dynamic_dims +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape // CHECK-SAME: {{\[}}[0, 1]{{\]}} : tensor<1x?xf32> into tensor // CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[5] high[6] // CHECK: } : tensor to tensor -// CHECK: tensor.expand_shape %[[PADDED]] -// CHECK-SAME: {{\[}}[0, 1]{{\]}} : tensor into tensor<1x?xf32> +// CHECK: %[[DIM:.+]] = tensor.dim %{{.*}}, %[[C1]] : tensor<1x?xf32> +// CHECK: %[[VAL_0:.+]] = affine.apply #[[$MAP]]()[%[[C1]], %[[DIM]]] +// CHECK: %[[VAL_1:.+]] = affine.apply #[[$MAP1]]()[%[[VAL_0]]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[PADDED]] {{\[\[}}0, 1]] output_shape [1, %[[VAL_1]]] : tensor into tensor<1x?xf32> // CHECK-SLICES: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 + 11)> @@ -1052,4 +1086,4 @@ func.func @drop_known_unit_constant_low_high(%arg0: tensor<1x383x128xf32>) -> te // CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0] high[0, 0] // CHECK: } : tensor<383x128xf32> to tensor<384x128xf32> // CHECK: tensor.expand_shape %[[PADDED]] -// CHECK-SAME: {{\[}}[0, 1], [2]] : tensor<384x128xf32> into tensor<1x384x128xf32> +// CHECK-SAME: {{\[}}[0, 1], [2]] output_shape [1, 384, 128] : tensor<384x128xf32> into tensor<1x384x128xf32> diff --git a/mlir/test/Dialect/Linalg/flatten-elementwise.mlir b/mlir/test/Dialect/Linalg/flatten-elementwise.mlir index 5a27fe76b134..9fe50a521d2d 100644 --- a/mlir/test/Dialect/Linalg/flatten-elementwise.mlir +++ b/mlir/test/Dialect/Linalg/flatten-elementwise.mlir @@ -26,7 +26,7 @@ module attributes {transform.with_named_sequence} { // CHECK-SAME: %[[ARG1:.*]]: tensor<32x7xf32> // CHECK-NEXT: %[[FLATTENED:.*]] = tensor.collapse_shape %[[ARG1]] {{\[}}[0, 1]] // CHECK-NEXT: %[[FLATTENED_RESULT:.*]] = linalg.fill ins(%[[ARG0]] : f32) outs(%[[FLATTENED]] : tensor<224xf32>) -// CHECK-NEXT: %[[RESULT:.*]] = tensor.expand_shape %[[FLATTENED_RESULT]] {{\[}}[0, 1]] +// CHECK-NEXT: %[[RESULT:.*]] = tensor.expand_shape %[[FLATTENED_RESULT]] {{\[}}[0, 1]] output_shape [32, 7] : tensor<224xf32> into tensor<32x7xf32> func.func @fill_tensor(%cst: f32, %arg: tensor<32x7xf32>) -> tensor<32x7xf32> { %0 = linalg.fill ins(%cst: f32) outs(%arg: tensor<32x7xf32>) -> tensor<32x7xf32> return %0 : tensor<32x7xf32> diff --git a/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir b/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir index 50d308b6a9fe..0d40df534a3b 100644 --- a/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir +++ b/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir @@ -9,8 +9,7 @@ #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing(%arg0 : tensor<2x12x5x336x9xi32>, %arg1 : tensor<2x3x4xi32>, %arg2 : tensor<5x6x7x8xi32>) -> tensor<2x3x4x5x6x7x8x9xi32> { - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] - : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [2, 3, 4, 5, 6, 7, 8, 9] : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> %init = tensor.empty() : tensor<2x3x4x5x6x7x8x9xi32> %generic = linalg.generic { indexing_maps = [#map0, #map1, #map2, #map3], @@ -40,7 +39,7 @@ func.func @fuse_by_collapsing(%arg0 : tensor<2x12x5x336x9xi32>, // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel", "parallel", "parallel"] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1_RESHAPE]], %[[ARG2_RESHAPE]] : // CHECK-SAME: outs(%[[INIT_RESHAPE]] : -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2], [3], [4, 5, 6], [7]{{\]}} +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2], [3], [4, 5, 6], [7]{{\]}} output_shape [2, 3, 4, 5, 6, 7, 8, 9] // CHECK: return %[[RESULT_RESHAPE]] // CONTROL: func @fuse_by_collapsing( @@ -60,8 +59,7 @@ func.func @fuse_by_collapsing(%arg0 : tensor<2x12x5x336x9xi32>, #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing_indexing_op(%arg0 : tensor<2x12x5x336x9xi32>, %arg1 : tensor<2x3x4xi32>, %arg2 : tensor<5x6x7x8xi32>) -> tensor<2x3x4x5x6x7x8x9xi32> { - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] - : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [2, 3, 4, 5, 6, 7, 8, 9] : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> %init = tensor.empty() : tensor<2x3x4x5x6x7x8x9xi32> %generic = linalg.generic { indexing_maps = [#map0, #map1, #map2, #map3], @@ -122,8 +120,7 @@ func.func @fuse_by_collapsing_indexing_op(%arg0 : tensor<2x12x5x336x9xi32>, #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing_change_reshape_order(%arg0 : tensor<9x56x2x60x6xi32>, %arg1 : tensor<7x8x2xi32>, %arg2 : tensor<6x3x4x5xi32>) -> tensor<2x3x4x5x6x7x8x9xi32> { - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] - : tensor<9x56x2x60x6xi32> into tensor<9x7x8x2x3x4x5x6xi32> + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [9, 7, 8, 2, 3, 4, 5, 6] : tensor<9x56x2x60x6xi32> into tensor<9x7x8x2x3x4x5x6xi32> %init = tensor.empty() : tensor<2x3x4x5x6x7x8x9xi32> %generic = linalg.generic { indexing_maps = [#map0, #map1, #map2, #map3], @@ -154,7 +151,7 @@ func.func @fuse_by_collapsing_change_reshape_order(%arg0 : tensor<9x56x2x60x6xi3 // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel", "parallel", "parallel"] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1_RESHAPE]], %[[ARG2_RESHAPE]] : // CHECK-SAME: outs(%[[INIT_RESHAPE]] : -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2, 3], [4], [5, 6], [7]{{\]}} +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2, 3], [4], [5, 6], [7]{{\]}} output_shape [2, 3, 4, 5, 6, 7, 8, 9] // CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -165,11 +162,11 @@ func.func @fuse_by_collapsing_change_reshape_order(%arg0 : tensor<9x56x2x60x6xi3 #map2 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d4, d1, d2, d3)> #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing_dynamic(%arg0 : tensor, - %arg1 : tensor, %arg2 : tensor) -> tensor { + %arg1 : tensor, %arg2 : tensor, %sz0: index, %sz1: index, %sz2: index, %sz3: index, %sz4: index) -> tensor { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [%sz0, 7, %sz1, %sz2, 3, %sz3, 5, %sz4] : tensor into tensor %d0 = tensor.dim %arg1, %c2 : tensor %d2 = tensor.dim %arg2, %c2 : tensor @@ -203,8 +200,8 @@ func.func @fuse_by_collapsing_dynamic(%arg0 : tensor, } -> tensor return %generic : tensor } -// CHECK: func @fuse_by_collapsing_dynamic( -// CHECK-SAME: %[[ARG0:.+]]: tensor +// CHECK: func @fuse_by_collapsing_dynamic +// CHECK-SAME: (%[[ARG0:.+]]: tensor, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index, %[[SZ2:.+]]: index, %[[SZ3:.+]]: index, %[[SZ4:.+]]: index) // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index // CHECK-DAG: %[[C5:.+]] = arith.constant 5 : index // CHECK: %[[EXPAND:.+]] = tensor.expand_shape %[[ARG0]] @@ -224,8 +221,8 @@ func.func @fuse_by_collapsing_dynamic(%arg0 : tensor, #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d3)> -func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>) -> tensor<2x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x?x5xf32> into tensor<2x6x?x5xf32> +func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>, %sz0: index) -> tensor<2x5xf32> { + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 6, %sz0, 5] : tensor<2x?x5xf32> into tensor<2x6x?x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1], iterator_types = ["parallel", "reduction", "reduction", "parallel"]} @@ -240,7 +237,8 @@ func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>) - // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2) -> (d0, d2)> // CHECK: func @fuse_reductions( // CHECK-SAME: %[[ARG0:.+]]: tensor<2x?x5xf32> -// CHECK-SAME: %[[ARG1:.+]]: tensor<2x5xf32>) -> tensor<2x5xf32> +// CHECK-SAME: %[[ARG1:.+]]: tensor<2x5xf32> +// CHECK-SAME: %[[SZ0:.+]]: index) -> tensor<2x5xf32> // CHECK: %[[GENERIC:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]]] // CHECK-SAME: iterator_types = ["parallel", "reduction", "parallel"] @@ -253,7 +251,7 @@ func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>) - #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1)> func.func @no_fuse_unpreserved_folding(%arg0 : tensor<2x12x5xf32>, %arg1 : tensor<2x3xf32>) -> tensor<2x3x4x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 3, 4, 5] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> %init = tensor.empty(): tensor<2x3x4x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1, #map0], @@ -280,7 +278,7 @@ func.func @no_fuse_unpreserved_folding(%arg0 : tensor<2x12x5xf32>, %arg1 : tenso #map1 = affine_map<(d0, d1, d2, d3) -> (d0)> #map2 = affine_map<(d0, d1, d2, d3) -> (d0, d2, d1, d3)> func.func @no_fuse_unpreserved_folding_transpose(%arg0 : tensor<2x12x5xf32>, %arg1 : tensor<2xf32>) -> tensor<2x4x3x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 3, 4, 5] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> %init = tensor.empty() : tensor<2x4x3x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1, #map2], @@ -307,7 +305,7 @@ func.func @no_fuse_unpreserved_folding_transpose(%arg0 : tensor<2x12x5xf32>, %ar #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1)> #map2 = affine_map<(d0, d1, d2, d3) -> (d0, d3)> func.func @no_fuse_mismatched_iterator_types(%arg0 : tensor<2x12x5xf32>, %arg1 : tensor<2x3xf32>) -> tensor<2x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 3, 4, 5] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> %init = tensor.empty() : tensor<2x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1, #map2], @@ -335,8 +333,8 @@ func.func @no_fuse_mismatched_iterator_types(%arg0 : tensor<2x12x5xf32>, %arg1 : #map1 = affine_map<(d0, d1, d2, d3) -> (d2, d3)> #map2 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> func.func @control_fusion(%arg0 : tensor<6xf32>, %arg1 : tensor<20xf32>) -> tensor<2x3x4x5xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1]] : tensor<6xf32> into tensor<2x3xf32> - %1 = tensor.expand_shape %arg1 [[0, 1]] : tensor<20xf32> into tensor<4x5xf32> + %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [2, 3] : tensor<6xf32> into tensor<2x3xf32> + %1 = tensor.expand_shape %arg1 [[0, 1]] output_shape [4, 5] : tensor<20xf32> into tensor<4x5xf32> %init = tensor.empty() : tensor<2x3x4x5xf32> %2 = linalg.generic { indexing_maps = [#map0, #map1, #map2], @@ -359,8 +357,8 @@ func.func @control_fusion(%arg0 : tensor<6xf32>, %arg1 : tensor<20xf32>) -> tens // CHECK-SAME: iterator_types = ["parallel", "parallel"] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1]] : // CHECK-SAME: outs(%{{.+}}: tensor<6x20xf32>) -// CHECK: %[[RESHAPE1:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1, 2]{{\]}} -// CHECK: %[[RESHAPE2:.+]] = tensor.expand_shape %[[RESHAPE1]] {{\[}}[0, 1], [2], [3]{{\]}} +// CHECK: %[[RESHAPE1:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1, 2]{{\]}} output_shape [6, 4, 5] +// CHECK: %[[RESHAPE2:.+]] = tensor.expand_shape %[[RESHAPE1]] {{\[}}[0, 1], [2], [3]{{\]}} output_shape [2, 3, 4, 5] // CHECK: return %[[RESHAPE2]] // CONTROL-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d1)> @@ -375,14 +373,14 @@ func.func @control_fusion(%arg0 : tensor<6xf32>, %arg1 : tensor<20xf32>) -> tens // CONTROL: %[[GENERIC:.+]] = linalg.generic // CONTROL-SAME: ins(%[[EXPAND]], %[[ARG1]] : // CONTROL-SAME: outs(%[[INIT_RESHAPE]] : -// CONTROL: %[[RESULT:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1], [2, 3]{{\]}} +// CONTROL: %[[RESULT:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1], [2, 3]{{\]}} output_shape [2, 3, 4, 5] // ----- // Corner case that isnt handled currently. #map = affine_map<(d0) -> (d0)> func.func @zero_D_test(%arg0: tensor) -> tensor<1xf32> { - %0 = tensor.expand_shape %arg0 [] : tensor into tensor<1xf32> + %0 = tensor.expand_shape %arg0 [] output_shape [1] : tensor into tensor<1xf32> %init = tensor.empty() : tensor<1xf32> %1 = linalg.generic { indexing_maps = [#map, #map], @@ -404,8 +402,8 @@ func.func @zero_D_test(%arg0: tensor) -> tensor<1xf32> { #map0 = affine_map<(d0, d1, d2, d3) -> (d1, d0, d2, d3)> #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> -func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4x?x?x8xf32>) -> tensor<4x?x?x8xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] : tensor into tensor +func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4x?x?x8xf32>, %sz0: index, %sz1: index) -> tensor<4x?x?x8xf32> { + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [%sz0, 4, %sz1, 8] : tensor into tensor %1 = linalg.generic { indexing_maps = [#map0, #map1, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} @@ -419,10 +417,12 @@ func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4 } // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d1, d0, d2)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> -// CHECK: func @fuse_only_one_reassociation( -// CHECK-SAME: %[[ARG0:.+]]: tensor -// CHECK-SAME: %[[ARG1:.+]]: tensor<4x?x?x8xf32> -// CHECK-DAG: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} +// CHECK: func @fuse_only_one_reassociation +// CHECK-SAME: (%[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor<4x?x?x8xf32>, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index) +// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index +// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index +// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index +// CHECK-DAG: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} output_shape [%[[SZ0]], 4, %[[SZ1]], 8] // CHECK-DAG: %[[COLLAPSE_ARG0:.+]] = tensor.collapse_shape %[[EXPAND_ARG0]] {{\[}}[0], [1], [2, 3]{{\]}} // CHECK-DAG: %[[COLLAPSE_ARG1_0:.+]] = tensor.collapse_shape %[[ARG1]] {{\[}}[0], [1], [2, 3]{{\]}} // CHECK-DAG: %[[COLLAPSE_ARG1_1:.+]] = tensor.collapse_shape %[[ARG1]] {{\[}}[0], [1], [2, 3]{{\]}} @@ -431,17 +431,20 @@ func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4 // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"] // CHECK-SAME: ins(%[[COLLAPSE_ARG0]], %[[COLLAPSE_ARG1_0]] : // CHECK-SAME: outs(%[[COLLAPSE_ARG1_1]] : -// CHECK: %[[EXPAND_GENERIC:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1], [2, 3]{{\]}} -// CHECK: return %[[EXPAND_GENERIC]] +// CHECK: %[[DIM:.+]] = tensor.dim %[[GENERIC]], %[[C1]] : tensor<4x?x?xf32> +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[GENERIC]], %[[C2]] : tensor<4x?x?xf32> +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C8]] : index +// CHECK: %[[EXPANDED_3:.+]] = tensor.expand_shape %[[GENERIC]] {{\[\[}}0], [1], [2, 3]] output_shape [4, %[[DIM]], %[[VAL_1]], 8] : tensor<4x?x?xf32> into tensor<4x?x?x8xf32> +// CHECK: return %[[EXPANDED_3]] // ----- #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d2, d3, d1)> #map1 = affine_map<(d0, d1, d2, d3) -> (d3, d1, d0, d2)> -func.func @fold_non_consecutive_dims(%arg0 : tensor) -> tensor { +func.func @fold_non_consecutive_dims(%arg0 : tensor, %sz0: index, %sz1: index) -> tensor { %c0 = arith.constant 0 : index %c2 = arith.constant 2 : index - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] : tensor into tensor + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [%sz0, 4, %sz1, 8] : tensor into tensor %d0 = tensor.dim %0, %c0 : tensor %d1 = tensor.dim %0, %c2 : tensor %init = tensor.empty(%d1, %d0) : tensor @@ -465,10 +468,16 @@ func.func @fold_non_consecutive_dims(%arg0 : tensor) -> tensor (d0, d1)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d1, d0)> // CHECK: func @fold_non_consecutive_dims( -// CHECK-SAME: %[[ARG0:.+]]: tensor) -// CHECK-DAG: %[[C4:.+]] = arith.constant 4 : index -// CHECK-DAG: %[[C8:.+]] = arith.constant 8 : index -// CHECK: %[[INIT:.+]] = tensor.empty +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index) +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C4:.+]] = arith.constant 4 : index +// CHECK: %[[C8:.+]] = arith.constant 8 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[C2:.+]] = arith.constant 2 : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[SZ0]], 4, %[[SZ1]], 8] : tensor into tensor +// CHECK: %[[DIM:.+]] = tensor.dim %[[EXPANDED]], %[[C0]] +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[EXPANDED]], %[[C2]] +// CHECK: %[[INIT:.+]] = tensor.empty(%[[DIM_0]], %[[DIM]]) // CHECK: %[[COLLAPSE_INIT:.+]] = tensor.collapse_shape %[[INIT]] {{\[}}[0, 1], [2, 3]{{\]}} // CHECK: %[[GENERIC:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]]] @@ -487,8 +496,12 @@ func.func @fold_non_consecutive_dims(%arg0 : tensor) -> tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[GENERIC]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_1]], %[[C8]] : index +// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_2]], %[[C4]] : index +// CHECK: %[[EXPANDED_3:.+]] = tensor.expand_shape %[[GENERIC]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_2]], 8, %[[VAL_3]], 4] : tensor into tensor +// CHECK: return %[[EXPANDED_3]] // ----- @@ -496,10 +509,10 @@ func.func @fold_non_consecutive_dims(%arg0 : tensor) -> tensor (d0, d2, d3, d1)> #map1 = affine_map<(d0, d1, d2, d3) -> ()> -func.func @no_fold_non_consecutive_reduction_dims(%arg0 : tensor) -> tensor { +func.func @no_fold_non_consecutive_reduction_dims(%arg0 : tensor, %sz0: index, %sz1: index) -> tensor { %c0 = arith.constant 0 : index %c2 = arith.constant 2 : index - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] : tensor into tensor + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [%sz0, 4, %sz1, 8] : tensor into tensor %init = tensor.empty() : tensor %1 = linalg.generic { indexing_maps = [#map0, #map1], @@ -519,8 +532,8 @@ func.func @no_fold_non_consecutive_reduction_dims(%arg0 : tensor) -> te return %1 : tensor } // CHECK: func @no_fold_non_consecutive_reduction_dims( -// CHECK-SAME: %[[ARG0:.+]]: tensor) -// CHECK: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index) +// CHECK: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} output_shape [%[[SZ0]], 4, %[[SZ1]], 8] // CHECK: %[[GENERIC:.+]] = linalg.generic // CHECK-SAME: ins(%[[EXPAND_ARG0]] : // CHECK: return %[[GENERIC]] diff --git a/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir b/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir index f1c729ef963b..751ece37bc09 100644 --- a/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir +++ b/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir @@ -4,15 +4,19 @@ // CHECK-DAG: #[[$MAP3:.*]] = affine_map<(d0, d1) -> (d1)> // CHECK-LABEL: func @reshape -// CHECK-SAME: (%[[A:.*]]: tensor, %[[B:.*]]: tensor<16xf32>, %[[INIT:.*]]: tensor) +// CHECK-SAME: (%[[A:.*]]: tensor, %[[B:.*]]: tensor<16xf32>, %[[INIT:.*]]: tensor, %[[SZ0:.*]]: index) +// CHECK: %[[C112:.*]] = arith.constant 112 : index +// CHECK: %[[C0:.*]] = arith.constant 0 : index // CHECK: %[[RI:.*]] = tensor.collapse_shape %[[INIT]] {{\[}}[0, 1], [2]] : tensor into tensor // CHECK: %[[R:.*]] = linalg.generic {indexing_maps = [#[[$MAP2]], #[[$MAP3]], #[[$MAP2]]], // CHECK-SAME: iterator_types = ["parallel", "parallel"]} // CHECK-SAME: ins(%[[A]], %[[B]] : tensor, tensor<16xf32>) outs(%[[RI]] : tensor) -// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[}}[0, 1], [2]] : tensor into tensor +// CHECK: %[[DIM:.*]] = tensor.dim %[[R]], %[[C0]] : tensor +// CHECK: %[[VAL_1:.*]] = arith.divui %[[DIM]], %[[C112]] : index +// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[\[}}0, 1], [2]] output_shape [%[[VAL_1]], 112, 16] : tensor into tensor // CHECK: return %[[RR]] : tensor -func.func @reshape(%A: tensor, %B: tensor<16xf32>, %init: tensor) -> tensor { - %0 = tensor.expand_shape %A [[0, 1], [2]] +func.func @reshape(%A: tensor, %B: tensor<16xf32>, %init: tensor, %sz0: index) -> tensor { + %0 = tensor.expand_shape %A [[0, 1], [2]] output_shape [%sz0, 112, 16] : tensor into tensor %2 = linalg.generic {indexing_maps = [ affine_map<(d0, d1, d2) -> (d0, d1, d2)>, affine_map<(d0, d1, d2) -> (d2)>, @@ -39,13 +43,13 @@ func.func @reshape(%A: tensor, %B: tensor<16xf32>, %init: tensor, tensor<12544x16xf32>, tensor<16xf32>) outs(%[[RI]] : tensor<12544x16xf32>) -// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[}}[0, 1], [2]] : tensor<12544x16xf32> into tensor<112x112x16xf32> +// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[}}[0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> // CHECK: return %[[RR]] : tensor<112x112x16xf32> func.func @reshape_multiple(%A: tensor<12544x16xf32>, %B: tensor<12544x16xf32>, %C: tensor<16xf32>) -> tensor<112x112x16xf32> { - %0 = tensor.expand_shape %A [[0, 1], [2]] + %0 = tensor.expand_shape %A [[0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> - %1 = tensor.expand_shape %B [[0, 1], [2]] + %1 = tensor.expand_shape %B [[0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> %2 = tensor.empty() : tensor<112x112x16xf32> %3 = linalg.generic {indexing_maps = [ @@ -69,11 +73,11 @@ func.func @reshape_multiple(%A: tensor<12544x16xf32>, %B: tensor<12544x16xf32>, // Negative test, since the second source is broadcasted from d1 we cannot merge // d0 and d1 dimensions // CHECK-LABEL: func @reshape_negative -// CHECK: tensor.expand_shape {{.*}} : tensor<12544x16xf32> into tensor<112x112x16xf32> +// CHECK: tensor.expand_shape {{.*}} {{\[\[}}0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> // CHECK: linalg.generic // CHECK: } -> tensor<112x112x16xf32> func.func @reshape_negative(%A: tensor<12544x16xf32>, %B: tensor<112xf32>) -> tensor<112x112x16xf32> { - %20 = tensor.expand_shape %A [[0, 1], [2]] + %20 = tensor.expand_shape %A [[0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> %21 = tensor.empty() : tensor<112x112x16xf32> %22 = linalg.generic {indexing_maps = [ @@ -96,7 +100,7 @@ func.func @type_correctness(%arg0 : tensor<6x5xi32>, %arg1 : tensor<5xf32>, %cst_6 = arith.constant 1.000000e+00 : f32 %cst_7 = arith.constant 7.000000e+00 : f32 %cst_8 = arith.constant 1.1920929E-7 : f32 - %25 = tensor.expand_shape %arg0 [[0, 1], [2]] + %25 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [2, 3, 5] : tensor<6x5xi32> into tensor<2x3x5xi32> %26 = tensor.empty() : tensor<2x3x5xf32> %28 = linalg.generic { diff --git a/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir b/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir index ab948988b7b6..0f0337a3604e 100644 --- a/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir +++ b/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir @@ -48,7 +48,7 @@ func.func @control_consumer_reshape_fusion(%arg0 : tensor<1x?x?xf32>, %arg1 : te ^bb0(%arg2: f32): linalg.yield %cst : f32 } -> tensor - %0 = tensor.expand_shape %fill [[0, 1], [2]] : tensor into tensor<1x?x?xf32> + %0 = tensor.expand_shape %fill [[0, 1], [2]] output_shape [1, %d0, %d1] : tensor into tensor<1x?x?xf32> %1 = linalg.batch_matmul ins(%arg0, %arg1 : tensor<1x?x?xf32>, tensor<1x?x?xf32>) outs(%0 : tensor<1x?x?xf32>) -> tensor<1x?x?xf32> return %1 : tensor<1x?x?xf32> diff --git a/mlir/test/Dialect/Linalg/reshape_fusion.mlir b/mlir/test/Dialect/Linalg/reshape_fusion.mlir index 342c067b5c4b..f42666f81bba 100644 --- a/mlir/test/Dialect/Linalg/reshape_fusion.mlir +++ b/mlir/test/Dialect/Linalg/reshape_fusion.mlir @@ -30,10 +30,20 @@ func.func @generic_op_reshape_producer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: f32 -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0], [1], [2, 3] -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0], [1], [2, 3] +// CHECK: %[[C4:.+]] = arith.constant 4 : index +// CHECK: %[[C2:.+]] = arith.constant 2 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C2]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM_1]], %[[C4]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1], [2, 3]] output_shape [%[[DIM]], %[[DIM_0]], %[[VAL_0]], 4] : tensor into tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_3:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG1]], %[[C2]] : tensor +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_4]], %[[C4]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1], [2, 3]] output_shape [%[[DIM_2]], %[[DIM_3]], %[[VAL_1]], 4] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP5]], #[[MAP6]], #[[MAP7]], #[[MAP6]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -50,7 +60,9 @@ func.func @generic_op_reshape_producer_fusion(%arg0 : tensor, #map1 = affine_map<(d0, d1) -> ()> func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, %arg1 : tensor, - %arg2 : f32) -> + %arg2 : f32, + %sz0: index, + %sz1: index) -> tensor { %0 = linalg.generic { @@ -63,7 +75,7 @@ func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, %2 = arith.addf %1, %arg5 : f32 linalg.yield %2 : f32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, 4, %sz1, 5] : tensor into tensor return %1 : tensor } @@ -75,14 +87,22 @@ func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: f32 -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor +// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index +// CHECK: %[[C20:.+]] = arith.constant 20 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM_0]], %[[C20]] : index +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM]], 4, %[[VAL_0]], 5] : tensor into tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C20]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_1]], 4, %[[VAL_1]], 5] : tensor into tensor +// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_5]], %[[C20]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_4]], 4, %[[VAL_2]], 5] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP2]], #[[MAP3]], #[[MAP2]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -94,7 +114,7 @@ func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, // ----- func.func @reshape_as_consumer_permutation - (%a : tensor, %b : tensor) + (%a : tensor, %b : tensor, %sz0: index, %sz1: index, %sz2: index) -> tensor { %c = linalg.generic { indexing_maps = [affine_map<(d0, d1, d2) -> (d1, d0, d2)>, @@ -107,8 +127,7 @@ func.func @reshape_as_consumer_permutation %1 = arith.addf %arg0, %arg1 : f32 linalg.yield %1 : f32 } -> tensor - %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] - : tensor into tensor + %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] output_shape [%sz0, 2, %sz1, 3, 4, %sz2] : tensor into tensor return %d : tensor } // CHECK-DAG: #[[MAP8:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d2, d3, d4, d0, d1, d5)> @@ -117,15 +136,27 @@ func.func @reshape_as_consumer_permutation // CHECK: func @reshape_as_consumer_permutation // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0, 1, 2], [3, 4], [5] -// CHECK-SAME: tensor into tensor<3x4x?x?x2x?xf32> -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0, 1, 2], [3] -// CHECK-SAME: tensor into tensor<3x4x?x?xf32> -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0, 1], [2], [3, 4, 5]] -// CHECK-SAME: tensor into tensor +// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index, %[[SZ2:.+]]: index +// CHECK: %[[C12:.+]] = arith.constant 12 : index +// CHECK: %[[C2:.+]] = arith.constant 2 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C12]] : index +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C2]] : index +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3, 4], [5]] output_shape [3, 4, %[[VAL_0]], %[[VAL_1]], 2, %[[DIM_1]]] : tensor into tensor<3x4x?x?x2x?xf32> +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_3:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_2]], %[[C12]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [3, 4, %[[VAL_2]], %[[DIM_3]]] : tensor into tensor<3x4x?x?xf32> +// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_6:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[DIM_7:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor +// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_5]], %[[C2]] : index +// CHECK: %[[VAL_4:.+]] = arith.divui %[[DIM_7]], %[[C12]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2], [3, 4, 5]] output_shape [%[[VAL_3]], 2, %[[DIM_6]], 3, 4, %[[VAL_4]]] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP8]], #[[MAP9]], #[[MAP10]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel", "parallel", "parallel"] @@ -152,7 +183,7 @@ func.func @generic_op_reshape_consumer_static(%arg0: tensor<264x4xf32>) %2 = arith.mulf %arg1, %arg2 : f32 linalg.yield %2 : f32 } -> tensor<264x4xf32> - %2 = tensor.expand_shape %1 [[0, 1], [2]] : + %2 = tensor.expand_shape %1 [[0, 1], [2]] output_shape [8, 33, 4] : tensor<264x4xf32> into tensor<8x33x4xf32> return %2 : tensor<8x33x4xf32> } @@ -163,12 +194,8 @@ func.func @generic_op_reshape_consumer_static(%arg0: tensor<264x4xf32>) // CHECK-DAG: %[[CST:.+]] = arith.constant // CHECK-SAME: : tensor<8x33x4xf32> // CHECK-DAG: %[[INIT:.+]] = tensor.empty() -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0, 1], [2] -// CHECK-SAME: tensor<264x4xf32> into tensor<8x33x4xf32> -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[INIT]] -// CHECK-SAME: [0, 1], [2] -// CHECK-SAME: : tensor<264x4xf32> into tensor<8x33x4xf32> +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2]] output_shape [8, 33, 4] : tensor<264x4xf32> into tensor<8x33x4xf32> +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1], [2]] output_shape [8, 33, 4] : tensor<264x4xf32> into tensor<8x33x4xf32> // CHECK: %[[T2:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP2]], #[[MAP2]]] // CHECK-SAME: ["parallel", "parallel", "parallel"] @@ -232,7 +259,8 @@ func.func @indexed_consumer_reshape_producer_fusion(%arg0 : tensor, #map0 = affine_map<(d0, d1) -> (d0, d1)> func.func @indexed_producer_reshape_consumer_fusion(%arg0 : tensor, - %arg1 : tensor) -> + %arg1 : tensor, + %sz0: index, %sz1: index) -> tensor { %0 = linalg.generic { @@ -250,7 +278,7 @@ func.func @indexed_producer_reshape_consumer_fusion(%arg0 : tensor, %5 = arith.addi %3, %4 : i32 linalg.yield %5 : i32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : tensor into tensor return %1 : tensor } @@ -302,8 +330,7 @@ func.func @reshape_as_consumer_permutation %7 = arith.addi %5, %6 : i32 linalg.yield %7 : i32 } -> tensor<6x4x210xi32> - %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] - : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> + %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] output_shape [2, 3, 4, 5, 6, 7] : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> return %d : tensor<2x3x4x5x6x7xi32> } @@ -319,13 +346,9 @@ func.func @reshape_as_consumer_permutation // CHECK-SAME: %[[ARG0:.+]]: tensor<210x6x4xi32> // CHECK-SAME: %[[ARG1:.+]]: tensor<210x4xi32> // CHECK-DAG: %[[INIT:.+]] = tensor.empty() -// CHECK-DAG: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0, 1, 2], [3, 4], [5] -// CHECK-DAG: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0, 1, 2], [3] -// CHECK-DAG: %[[T3:.+]] = tensor.expand_shape %[[INIT]] -// CHECK-SAME: [0, 1], [2], [3, 4, 5] -// CHECK-SAME: : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3, 4], [5]] output_shape [5, 6, 7, 2, 3, 4] : tensor<210x6x4xi32> into tensor<5x6x7x2x3x4xi32> +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [5, 6, 7, 4] : tensor<210x4xi32> into tensor<5x6x7x4xi32> +// CHECK: %[[T3:.+]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1], [2], [3, 4, 5]] output_shape [2, 3, 4, 5, 6, 7] : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> // CHECK: %[[T4:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]]] // CHECK-SAME: ins(%[[T1]], %[[T2]] : tensor<5x6x7x2x3x4xi32>, tensor<5x6x7x4xi32>) @@ -411,7 +434,8 @@ func.func @reshape_as_producer_projected_permutation( #map0 = affine_map<(d0, d1) -> (d0, d1)> #map1 = affine_map<(d0, d1) -> (d1, d0)> func.func @generic_op_reshape_consumer_fusion_projected(%arg0 : tensor, - %arg1 : tensor) -> + %arg1 : tensor, + %sz0: index, %sz1: index) -> tensor { %0 = linalg.generic { @@ -423,7 +447,7 @@ func.func @generic_op_reshape_consumer_fusion_projected(%arg0 : tensor, %1 = arith.mulf %arg3, %arg4 : f32 linalg.yield %1 : f32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : tensor into tensor return %1 : tensor } @@ -433,15 +457,22 @@ func.func @generic_op_reshape_consumer_fusion_projected(%arg0 : tensor, // CHECK: func @generic_op_reshape_consumer_fusion_projected // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0, 1, 2], [3] -// CHECK-SAME: tensor into tensor -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0, 1, 2], [3] -// CHECK-SAME: tensor into tensor -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor +// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index +// CHECK: %[[C20:.+]] = arith.constant 20 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C20]] : index +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[VAL_0]], 4, 5, %[[DIM_0]]] : tensor into tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_1]], %[[C20]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[VAL_1]], 4, 5, %[[DIM_2]]] : tensor into tensor +// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_5]], %[[C20]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_4]], %[[VAL_2]], 4, 5] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP4]], #[[MAP4]], #[[MAP5]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -466,6 +497,7 @@ func.func @no_fuse_dynamic_dims(%arg0: tensor) -> tensor { } -> tensor return %3 : tensor } + // CHECK: func @no_fuse_dynamic_dims // CHECK-SAME: %[[ARG0:.+]]: tensor // CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] @@ -503,7 +535,8 @@ func.func @no_fuse_mismatched_dynamism(%arg0: tensor<2x1xi64>, %arg1: tensor, %b : tensor) + (%a : tensor, %b : tensor, %sz0: index, + %sz1: index, %sz2: index, %sz3: index, %sz4: index) -> (tensor, tensor) { %c:2 = linalg.generic { indexing_maps = [affine_map<(d0, d1, d2) -> (d1, d0, d2)>, @@ -517,10 +550,8 @@ func.func @reshape_as_consumer_permutation_with_multiple_results %1 = arith.addf %arg0, %arg1 : f32 linalg.yield %1, %1 : f32, f32 } -> (tensor, tensor) - %d = tensor.expand_shape %c#0 [[0, 1], [2], [3, 4, 5]] - : tensor into tensor - %e = tensor.expand_shape %c#1 [[0], [1, 2], [3, 4, 5]] - : tensor into tensor + %d = tensor.expand_shape %c#0 [[0, 1], [2], [3, 4, 5]] output_shape [%sz0, 2, %sz1, 3, 4, %sz2] : tensor into tensor + %e = tensor.expand_shape %c#1 [[0], [1, 2], [3, 4, 5]] output_shape [%sz3, %sz4, 2, 3, 4, %sz2] : tensor into tensor return %d, %e : tensor, tensor } // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d2, d3, d4, d0, d1, d5)> @@ -528,17 +559,40 @@ func.func @reshape_as_consumer_permutation_with_multiple_results // CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d5, d2, d3, d4)> // CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d5, d0, d1, d2, d3, d4)> // CHECK: func @reshape_as_consumer_permutation_with_multiple_results -// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: tensor -// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: tensor -// CHECK-DAG: %[[RESHAPE0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3, 4], [5]{{\]}} -// CHECK-DAG: %[[RESHAPE1:.+]] = tensor.expand_shape %[[ARG1]] {{\[}}[0, 1, 2], [3]{{\]}} -// CHECK-DAG: %[[RESHAPE2:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3, 4, 5]{{\]}} -// CHECK-DAG: %[[RESHAPE3:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2], [3, 4, 5]{{\]}} -// CHECK: %[[GENERIC:.+]]:2 = linalg.generic -// CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]]] -// CHECK-SAME: ins(%[[RESHAPE0]], %[[RESHAPE1]] : -// CHECK-SAME: outs(%[[RESHAPE2]], %[[RESHAPE3]] : -// CHECK: return %[[GENERIC]]#0, %[[GENERIC]]#1 +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: tensor +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: tensor +// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index, %[[SZ2:.+]]: index, %[[SZ3:.+]]: index, %[[SZ4:.+]]: index +// CHECK: %[[C12:.+]] = arith.constant 12 : index +// CHECK: %[[C2:.+]] = arith.constant 2 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C12]] : index +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C2]] : index +// CHECK: %[[RESHAPE0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3, 4], [5]] output_shape [3, 4, %[[VAL_0]], %[[VAL_1]], 2, %[[DIM_1]]] : tensor into tensor<3x4x?x?x2x?xf32> +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_3:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_2]], %[[C12]] : index +// CHECK: %[[RESHAPE1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [3, 4, %[[VAL_2]], %[[DIM_3]]] : tensor into tensor<3x4x?x?xf32> +// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_6:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[DIM_7:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor +// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_5]], %[[C2]] : index +// CHECK: %[[VAL_4:.+]] = arith.divui %[[DIM_7]], %[[C12]] : index +// CHECK: %[[RESHAPE2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2], [3, 4, 5]] output_shape [%[[VAL_3]], 2, %[[DIM_6]], 3, 4, %[[VAL_4]]] : tensor into tensor +// CHECK: %[[DIM_9:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_10:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[DIM_11:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor +// CHECK: %[[VAL_5:.+]] = arith.divui %[[DIM_10]], %[[C2]] : index +// CHECK: %[[VAL_6:.+]] = arith.divui %[[DIM_11]], %[[C12]] : index +// CHECK: %[[RESHAPE3:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2], [3, 4, 5]] output_shape [%[[DIM_9]], %[[VAL_5]], 2, 3, 4, %[[VAL_6]]] : tensor into tensor +// CHECK: %[[GENERIC:.+]]:2 = linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]]] +// CHECK-SAME: ins(%[[RESHAPE0]], %[[RESHAPE1]] : +// CHECK-SAME: outs(%[[RESHAPE2]], %[[RESHAPE3]] : +// CHECK: return %[[GENERIC]]#0, %[[GENERIC]]#1 // ----- @@ -556,7 +610,7 @@ module { %2 = arith.addf %arg4, %arg5 : f32 linalg.yield %2, %2 : f32, f32 } -> (tensor<512xf32>, tensor<200x512xf32>) - %1 = tensor.expand_shape %0#1 [[0, 1, 2], [3]] : tensor<200x512xf32> into tensor<25x8x1x512xf32> + %1 = tensor.expand_shape %0#1 [[0, 1, 2], [3]] output_shape [25, 8, 1, 512] : tensor<200x512xf32> into tensor<25x8x1x512xf32> return %1 : tensor<25x8x1x512xf32> } } @@ -567,7 +621,7 @@ module { // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: tensor<512xf32> // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: tensor<512xf32> // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: tensor<200x512xf32> -// CHECK: %[[OUTS:.+]] = tensor.expand_shape %[[ARG3]] {{\[}}[0, 1, 2], [3]{{\]}} +// CHECK: %[[OUTS:.+]] = tensor.expand_shape %[[ARG3]] {{\[\[}}0, 1, 2], [3]] output_shape [25, 8, 1, 512] : tensor<200x512xf32> into tensor<25x8x1x512xf32> // CHECK: %[[GENERIC:.+]]:2 = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP0]], #[[MAP0]], #[[MAP1]]] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1]] : @@ -581,7 +635,9 @@ module { #map2 = affine_map<(d0, d1, d2) -> (d0, d1)> func.func @generic_op_reshape_consumer_fusion_reduction(%arg0 : tensor, %arg1 : tensor, - %arg2 : tensor) -> + %arg2 : tensor, + %sz0: index, + %sz1: index) -> tensor { %0 = linalg.generic { @@ -593,7 +649,7 @@ func.func @generic_op_reshape_consumer_fusion_reduction(%arg0 : tensor, %1 = arith.mulf %arg3, %arg4 : f32 linalg.yield %1 : f32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : tensor into tensor return %1 : tensor } @@ -605,12 +661,18 @@ func.func @generic_op_reshape_consumer_fusion_reduction(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0, 1, 2], [3] -// CHECK-SAME: tensor into tensor -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor +// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index +// CHECK: %[[C20:.+]] = arith.constant 20 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C20]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[VAL_0]], 4, 5, %[[DIM_0]]] : tensor into tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C20]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_1]], %[[VAL_1]], 4, 5] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel", "reduction"] @@ -650,10 +712,21 @@ func.func @generic_op_reshape_producer_fusion_with_reduction(%arg0 : tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0, 1], [2], [3, 4] -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] -// CHECK-SAME: [0, 1], [2, 3] +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C7:.+]] = arith.constant 7 : index +// CHECK: %[[C8:.+]] = arith.constant 8 : index +// CHECK: %[[C2:.+]] = arith.constant 2 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C2]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C8]] : index +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C7]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1], [2], [3, 4]] output_shape [%[[VAL_0]], 8, 4, %[[VAL_1]], 7] : tensor into tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_1]], %[[C8]] : index +// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_2]], %[[C7]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_2]], 8, %[[VAL_3]], 7] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]] // CHECK-SAME: ["parallel", "parallel", "reduction", "parallel", "parallel"] @@ -668,12 +741,14 @@ func.func @generic_op_reshape_producer_fusion_with_reduction(%arg0 : tensor, %arg1 : tensor, - %arg2 : tensor) -> + %arg2 : tensor, + %sz0: index, + %sz1: index) -> tensor { %0 = linalg.add ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : tensor into tensor return %1 : tensor } @@ -683,15 +758,22 @@ func.func @linalg_add_reshape_consumer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor -// CHECK: %[[T3:.+]] = tensor.expand_shape %[[ARG2]] -// CHECK-SAME: [0], [1, 2, 3] -// CHECK-SAME: tensor into tensor +// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index +// CHECK: %[[C20:.+]] = arith.constant 20 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM_0]], %[[C20]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM]], %[[VAL_0]], 4, 5] : tensor into tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C20]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_1]], %[[VAL_1]], 4, 5] : tensor into tensor +// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor +// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_5]], %[[C20]] : index +// CHECK: %[[T3:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_4]], %[[VAL_2]], 4, 5] : tensor into tensor // CHECK: %[[T4:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -721,10 +803,20 @@ func.func @linalg_add_reshape_producer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] -// CHECK-SAME: [0, 1], [2, 3] -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] -// CHECK-SAME: [0, 1], [2, 3] +// CHECK: %[[C8:.+]] = arith.constant 8 : index +// CHECK: %[[C7:.+]] = arith.constant 7 : index +// CHECK: %[[C1:.+]] = arith.constant 1 : index +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor +// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor +// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C7]] : index +// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C8]] : index +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_0]], 7, %[[VAL_1]], 8] : tensor into tensor +// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor +// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor +// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_1]], %[[C7]] : index +// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_2]], %[[C8]] : index +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_2]], 7, %[[VAL_3]], 8] : tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP]], #[[$MAP]], #[[$MAP]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] diff --git a/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir b/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir index 4262cd23e746..8fb84248c961 100644 --- a/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir +++ b/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir @@ -199,13 +199,12 @@ func.func @empty_tensor_dim_of_linalg_result(%arg_0 : tensor, // ----- -func.func @dim_reshape_expansion(%arg0 : tensor<6x5x?xf32>) -> (index, index, index) +func.func @dim_reshape_expansion(%arg0 : tensor<6x5x?xf32>, %sz0: index) -> (index, index, index) { %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index %c4 = arith.constant 4 : index - %0 = tensor.expand_shape %arg0 [[0, 1], [2], [3, 4, 5]] - : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> + %0 = tensor.expand_shape %arg0 [[0, 1], [2], [3, 4, 5]] output_shape [2, 3, 5, 4, %sz0, 7] : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> %1 = tensor.dim %0, %c1 : tensor<2x3x5x4x?x7xf32> %2 = tensor.dim %0, %c3 : tensor<2x3x5x4x?x7xf32> %3 = tensor.dim %0, %c4 : tensor<2x3x5x4x?x7xf32> diff --git a/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir b/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir index 006d6105677e..31e9fd00cffa 100644 --- a/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir +++ b/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir @@ -13,8 +13,8 @@ func.func @matmul_split(%A : tensor<16x256xf32>, %B: tensor<256x32xf32>, %C: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: @matmul_split // CHECK-DAG: %[[ID:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<16x256xf32> into tensor<16x4x64xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<256x32xf32> into tensor<4x64x32xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [16, 4, 64] : tensor<16x256xf32> into tensor<16x4x64xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [4, 64, 32] : tensor<256x32xf32> into tensor<4x64x32xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<16x32x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<16x32x4xf32>) -> tensor<16x32x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]] @@ -65,7 +65,7 @@ func.func @generic_split_1d(%arg0: tensor<32xf32>, %arg1: tensor, %out: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0) -> ()> //CHECK-LABEL: @generic_split_1d // CHECK-DAG: %[[ID:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] : tensor<32xf32> into tensor<4x8xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] output_shape [4, 8] : tensor<32xf32> into tensor<4x8xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<4xf32>) -> tensor<4xf32> // CHECK: %[[G:.*]] = linalg.generic @@ -119,8 +119,8 @@ func.func @generic_split_3d(%input: tensor<32x2xf32>, %input_2: tensor<5x32xf32> // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d // CHECK-DAG: %[[ID:.*]] = arith.constant 0xFF800000 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<4x8x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x4x8xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [4, 8, 2] : tensor<32x2xf32> into tensor<4x8x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 4, 8] : tensor<5x32xf32> into tensor<5x4x8xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} @@ -177,8 +177,8 @@ func.func @generic_split_3d_ninf(%input: tensor<32x2xf32>, %input_2: tensor<5x32 // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d_ninf // CHECK-DAG: %[[ID:.*]] = arith.constant -3.40282347E+38 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<4x8x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x4x8xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [4, 8, 2] : tensor<32x2xf32> into tensor<4x8x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 4, 8] : tensor<5x32xf32> into tensor<5x4x8xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} @@ -218,8 +218,8 @@ func.func @matmul_split(%A : tensor<16x256xf32>, %B: tensor<256x32xf32>, %C: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: @matmul_split // CHECK-DAG: %[[ID:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<16x256xf32> into tensor<16x64x4xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<256x32xf32> into tensor<64x4x32xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [16, 64, 4] : tensor<16x256xf32> into tensor<16x64x4xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [64, 4, 32] : tensor<256x32xf32> into tensor<64x4x32xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<16x32x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<16x32x4xf32>) -> tensor<16x32x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]] @@ -270,7 +270,7 @@ func.func @generic_split_1d(%arg0: tensor<32xf32>, %arg1: tensor, %out: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0) -> ()> //CHECK-LABEL: @generic_split_1d // CHECK-DAG: %[[ID:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] : tensor<32xf32> into tensor<8x4xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] output_shape [8, 4] : tensor<32xf32> into tensor<8x4xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<4xf32>) -> tensor<4xf32> // CHECK: %[[G:.*]] = linalg.generic @@ -324,8 +324,8 @@ func.func @generic_split_3d(%input: tensor<32x2xf32>, %input_2: tensor<5x32xf32> // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d // CHECK-DAG: %[[ID:.*]] = arith.constant 0x7F800000 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<8x4x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x8x4xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [8, 4, 2] : tensor<32x2xf32> into tensor<8x4x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 8, 4] : tensor<5x32xf32> into tensor<5x8x4xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} @@ -382,8 +382,8 @@ func.func @generic_split_3d(%input: tensor<32x2xf32>, %input_2: tensor<5x32xf32> // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d // CHECK-DAG: %[[ID:.*]] = arith.constant 3.40282347E+38 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<8x4x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x8x4xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [8, 4, 2] : tensor<32x2xf32> into tensor<8x4x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 8, 4] : tensor<5x32xf32> into tensor<5x8x4xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} diff --git a/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir b/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir index 58d4b21ea2dd..d7ff1ded9d93 100644 --- a/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir +++ b/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir @@ -1710,10 +1710,12 @@ module attributes {transform.with_named_sequence} { #map = affine_map<(d0) -> (d0)> // CHECK-LABEL: @not_vectorizable func.func @not_vectorizable(%arg0: tensor<1x?xf32>, %arg1: index, %arg2: index, %arg3: index) -> tensor<1x128xf32> { + %c0 = arith.constant 0 : index %0 = tensor.empty() : tensor<1x128xf32> %1 = scf.for %arg5 = %arg2 to %arg1 step %arg3 iter_args(%arg6 = %0) -> (tensor<1x128xf32>) { %extracted_slice = tensor.extract_slice %arg6[0, 0] [1, %arg1] [1, 1] : tensor<1x128xf32> to tensor - %expanded = tensor.expand_shape %extracted_slice [[0, 1]] : tensor into tensor<1x?xf32> + %sz0 = tensor.dim %extracted_slice, %c0 : tensor + %expanded = tensor.expand_shape %extracted_slice [[0, 1]] output_shape [1, %sz0] : tensor into tensor<1x?xf32> %extracted_slice_0 = tensor.extract_slice %arg0[0, %arg3] [1, %arg2] [1, 1] : tensor<1x?xf32> to tensor %extracted_slice_1 = tensor.extract_slice %expanded[0, %arg3] [1, %arg2] [1, 1] : tensor<1x?xf32> to tensor %2 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel"]} ins(%extracted_slice_0 : tensor) outs(%extracted_slice_1 : tensor) { diff --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir index 506ed1f1c10b..f442a61dc31e 100644 --- a/mlir/test/Dialect/MemRef/canonicalize.mlir +++ b/mlir/test/Dialect/MemRef/canonicalize.mlir @@ -13,7 +13,7 @@ func.func @collapse_shape_identity_fold(%arg0 : memref<5xi8>) -> memref<5xi8> { // CHECK-LABEL: expand_shape_identity_fold // CHECK-NEXT: return func.func @expand_shape_identity_fold(%arg0 : memref<5x4xi8>) -> memref<5x4xi8> { - %0 = memref.expand_shape %arg0 [[0], [1]] : memref<5x4xi8> into memref<5x4xi8> + %0 = memref.expand_shape %arg0 [[0], [1]] output_shape [5, 4] : memref<5x4xi8> into memref<5x4xi8> return %0 : memref<5x4xi8> } @@ -23,7 +23,7 @@ func.func @expand_shape_identity_fold(%arg0 : memref<5x4xi8>) -> memref<5x4xi8> // CHECK-NEXT: return func.func @collapse_expand_rank0_cancel(%arg0 : memref<1x1xi8>) -> memref<1x1xi8> { %0 = memref.collapse_shape %arg0 [] : memref<1x1xi8> into memref - %1 = memref.expand_shape %0 [] : memref into memref<1x1xi8> + %1 = memref.expand_shape %0 [] output_shape [1, 1] : memref into memref<1x1xi8> return %1 : memref<1x1xi8> } @@ -455,9 +455,9 @@ func.func @compose_collapse_of_collapse(%arg0 : memref) // ----- func.func @do_not_compose_collapse_of_expand_non_identity_layout( - %arg0: memref>) + %arg0: memref>, %sz0: index, %sz1: index) -> memref> { - %1 = memref.expand_shape %arg0 [[0, 1], [2]] : + %1 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, %sz1] : memref> into memref> %2 = memref.collapse_shape %1 [[0, 1, 2]] : @@ -471,35 +471,34 @@ func.func @do_not_compose_collapse_of_expand_non_identity_layout( // ----- -func.func @compose_expand_of_expand(%arg0 : memref) +func.func @compose_expand_of_expand(%arg0 : memref, %sz0: index, %sz1: index, %sz2: index, %sz3: index) -> memref { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, %sz1] : memref into memref - %1 = memref.expand_shape %0 [[0, 1], [2], [3, 4]] - : memref into memref + %1 = memref.expand_shape %0 [[0, 1], [2], [3, 4]] output_shape [%sz2, 6, 4, 5, %sz3] : memref into memref return %1 : memref } // CHECK-LABEL: func @compose_expand_of_expand -// CHECK: memref.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] +// CHECK: memref.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] output_shape [%{{.*}}, 6, 4, 5, %{{.*}}] // CHECK-NOT: memref.expand_shape // ----- func.func @compose_expand_of_expand_of_zero_dim(%arg0 : memref) -> memref<1x1x1xf32> { - %0 = memref.expand_shape %arg0 [] : memref into memref<1xf32> - %1 = memref.expand_shape %0 [[0, 1, 2]] + %0 = memref.expand_shape %arg0 [] output_shape [1] : memref into memref<1xf32> + %1 = memref.expand_shape %0 [[0, 1, 2]] output_shape [1, 1, 1] : memref<1xf32> into memref<1x1x1xf32> return %1 : memref<1x1x1xf32> } // CHECK-LABEL: func @compose_expand_of_expand_of_zero_dim -// CHECK: memref.expand_shape %{{.*}} [] +// CHECK: memref.expand_shape %{{.*}} [] output_shape [1, 1, 1] // CHECK-SAME: memref into memref<1x1x1xf32> // ----- func.func @fold_collapse_of_expand(%arg0 : memref<12x4xf32>) -> memref<12x4xf32> { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [3, 4, 4] : memref<12x4xf32> into memref<3x4x4xf32> %1 = memref.collapse_shape %0 [[0, 1], [2]] : memref<3x4x4xf32> into memref<12x4xf32> @@ -510,9 +509,9 @@ func.func @fold_collapse_of_expand(%arg0 : memref<12x4xf32>) -> memref<12x4xf32> // ----- -func.func @fold_collapse_collapse_of_expand(%arg0 : memref) +func.func @fold_collapse_collapse_of_expand(%arg0 : memref, %sz0: index, %sz1: index) -> memref { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, %sz1] : memref into memref %1 = memref.collapse_shape %0 [[0, 1], [2]] : memref into memref @@ -525,7 +524,7 @@ func.func @fold_collapse_collapse_of_expand(%arg0 : memref) func.func @fold_memref_expand_cast(%arg0 : memref) -> memref<2x4x4xf32> { %0 = memref.cast %arg0 : memref to memref<8x4xf32> - %1 = memref.expand_shape %0 [[0, 1], [2]] + %1 = memref.expand_shape %0 [[0, 1], [2]] output_shape [2, 4, 4] : memref<8x4xf32> into memref<2x4x4xf32> return %1 : memref<2x4x4xf32> } @@ -981,10 +980,10 @@ func.func @memref_realloc_dead(%src : memref<2xf32>, %v : f32) -> memref<2xf32>{ // CHECK-SAME: %[[m:.*]]: memref, 3> // CHECK: %[[casted:.*]] = memref.cast %[[m]] : memref, 3> to memref, 3>) +func.func @collapse_expand_fold_to_cast(%m: memref, 3>, %sz0: index) -> (memref) { - %0 = memref.expand_shape %m [[0, 1]] + %0 = memref.expand_shape %m [[0, 1]] output_shape [1, %sz0] : memref, 3> into memref<1x?xf32, 3> %1 = memref.collapse_shape %0 [[0, 1]] : memref<1x?xf32, 3> into memref diff --git a/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir b/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir index 28b700430059..fdfaa72168d1 100644 --- a/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir +++ b/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir @@ -421,10 +421,11 @@ func.func @simplify_expand_shape( %base: memref>, %offset0: index, %offset1: index, %offset2: index, %size0: index, %size1: index, %size2: index, - %stride0: index, %stride1: index, %stride2: index) + %stride0: index, %stride1: index, %stride2: index, + %sz0: index, %sz1: index) -> memref> { - %subview = memref.expand_shape %base[[0, 1, 2, 3],[4, 5, 6, 7]] : + %subview = memref.expand_shape %base [[0, 1, 2, 3],[4, 5, 6, 7]] output_shape [%sz0, 7, 8, 9, 10, 2, %sz1, 3] : memref> into memref> @@ -491,7 +492,7 @@ func.func @extract_strided_metadata_of_expand_shape_all_static( index, index, index, index, index, index, index, index, index, index) { - %expand_shape = memref.expand_shape %arg[[0, 1, 2], [3, 4]] : + %expand_shape = memref.expand_shape %arg[[0, 1, 2], [3, 4]] output_shape [3, 5, 2, 2, 2] : memref<30x4xi16> into memref<3x5x2x2x2xi16> %base, %offset, %sizes:5, %strides:5 = memref.extract_strided_metadata %expand_shape : @@ -595,12 +596,13 @@ func.func @extract_strided_metadata_of_expand_shape_all_dynamic( %base: memref>, %offset0: index, %offset1: index, %offset2: index, %size0: index, %size1: index, %size2: index, - %stride0: index, %stride1: index, %stride2: index) + %stride0: index, %stride1: index, %stride2: index, + %sz0: index, %sz1: index) -> (memref, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index) { - %subview = memref.expand_shape %base[[0, 1, 2, 3],[4, 5, 6, 7]] : + %subview = memref.expand_shape %base[[0, 1, 2, 3],[4, 5, 6, 7]] output_shape [%sz0, 7, 8, 9, 10, 2, %sz1, 3] : memref> into memref> @@ -643,7 +645,7 @@ func.func @extract_strided_metadata_of_expand_shape_all_static_0_rank( index, index, index, index, index, index, index, index, index, index) { - %expand_shape = memref.expand_shape %arg[] : + %expand_shape = memref.expand_shape %arg[] output_shape [1, 1, 1, 1, 1] : memref> into memref<1x1x1x1x1xi16, strided<[1,1,1,1,1], offset: ?>> %base, %offset, %sizes:5, %strides:5 = memref.extract_strided_metadata %expand_shape : @@ -1513,4 +1515,4 @@ func.func @zero_sized_memred(%arg0: f32) -> (memref, index,index,index) %sizes, %strides : memref, index, index, index -} \ No newline at end of file +} diff --git a/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir b/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir index 5b853a6cc5a3..254cd4015eed 100644 --- a/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir +++ b/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir @@ -412,7 +412,7 @@ func.func @fold_static_stride_subview_with_affine_load_store(%arg0 : memref<12x3 // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape // CHECK-SAME: (%[[ARG0:.*]]: memref<12x32xf32>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index) -> f32 { func.func @fold_static_stride_subview_with_affine_load_store_expand_shape(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref<12x32xf32> into memref<2x6x32xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [2, 6, 32] : memref<12x32xf32> into memref<2x6x32xf32> %1 = affine.load %0[%arg1, %arg2, %arg3] : memref<2x6x32xf32> return %1 : f32 } @@ -458,7 +458,7 @@ func.func @fold_dynamic_size_collapse_shape_with_affine_load(%arg0 : memref, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index, %[[ARG4:.*]]: index) -> f32 { func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_3d(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1, 2], [3]] : memref<12x32xf32> into memref<2x2x3x32xf32> + %0 = memref.expand_shape %arg0 [[0, 1, 2], [3]] output_shape [2, 2, 3, 32] : memref<12x32xf32> into memref<2x2x3x32xf32> %1 = affine.load %0[%arg1, %arg2, %arg3, %arg4] : memref<2x2x3x32xf32> return %1 : f32 } @@ -469,15 +469,17 @@ func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_3d(%ar // ----- // CHECK-LABEL: fold_dynamic_subview_with_memref_load_store_expand_shape -func.func @fold_dynamic_subview_with_memref_load_store_expand_shape(%arg0 : memref<16x?xf32, strided<[16, 1]>>, %arg1 : index, %arg2 : index) -> f32 { +// CHECK-SAME: (%[[ARG0:.*]]: memref<16x?xf32, strided<[16, 1]>>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[SZ0:.*]]: index) +func.func @fold_dynamic_subview_with_memref_load_store_expand_shape(%arg0 : memref<16x?xf32, strided<[16, 1]>>, %arg1 : index, %arg2 : index, %sz0: index) -> f32 { %c0 = arith.constant 0 : index - %expand_shape = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> + %expand_shape = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 16, %sz0, 1] : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> %0 = memref.load %expand_shape[%c0, %arg1, %arg2, %c0] : memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> return %0 : f32 } -// CHECK: %[[EXPAND_SHAPE:.+]] = memref.expand_shape {{.+}} : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> -// CHECK: %[[LOAD:.+]] = memref.load %[[EXPAND_SHAPE]] -// CHECK: return %[[LOAD]] +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[EXPAND_SHAPE:.*]] = memref.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2, 3]] output_shape [1, 16, %[[SZ0]], 1] : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> +// CHECK: %[[VAL_0:.*]] = memref.load %[[EXPAND_SHAPE]][%[[C0]], %[[ARG1]], %[[ARG2]], %[[C0]]] : memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> +// CHECK: return %[[VAL_0]] : f32 // ----- @@ -486,7 +488,7 @@ func.func @fold_dynamic_subview_with_memref_load_store_expand_shape(%arg0 : memr // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape // CHECK-SAME: (%[[ARG0:.*]]: memref<1024x1024xf32>, %[[ARG1:.*]]: memref<1xf32>, %[[ARG2:.*]]: index) func.func @fold_static_stride_subview_with_affine_load_store_expand_shape(%arg0: memref<1024x1024xf32>, %arg1: memref<1xf32>, %arg2: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 1024, 1024, 1] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> affine.for %arg3 = 0 to 1 { affine.for %arg4 = 0 to 1024 { affine.for %arg5 = 0 to 1020 { @@ -515,7 +517,7 @@ func.func @fold_static_stride_subview_with_affine_load_store_expand_shape(%arg0: // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape_when_access_index_is_an_expression // CHECK-SAME: (%[[ARG0:.*]]: memref<1024x1024xf32>, %[[ARG1:.*]]: memref<1xf32>, %[[ARG2:.*]]: index) func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_when_access_index_is_an_expression(%arg0: memref<1024x1024xf32>, %arg1: memref<1xf32>, %arg2: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 1024, 1024, 1] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> affine.for %arg3 = 0 to 1 { affine.for %arg4 = 0 to 1024 { affine.for %arg5 = 0 to 1020 { @@ -544,7 +546,7 @@ func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_when_a // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape_with_constant_access_index // CHECK-SAME: (%[[ARG0:.*]]: memref<1024x1024xf32>, %[[ARG1:.*]]: memref<1xf32>, %[[ARG2:.*]]: index) func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_with_constant_access_index(%arg0: memref<1024x1024xf32>, %arg1: memref<1xf32>, %arg2: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 1024, 1024, 1] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> %cst = arith.constant 0 : index affine.for %arg3 = 0 to 1 { affine.for %arg4 = 0 to 1024 { diff --git a/mlir/test/Dialect/MemRef/invalid.mlir b/mlir/test/Dialect/MemRef/invalid.mlir index 1aef417549d9..21bbffc5b5a9 100644 --- a/mlir/test/Dialect/MemRef/invalid.mlir +++ b/mlir/test/Dialect/MemRef/invalid.mlir @@ -392,9 +392,9 @@ func.func @copy_different_eltype(%arg0: memref<2xf32>, %arg1: memref<2xf16>) { // ----- -func.func @expand_shape(%arg0: memref) { +func.func @expand_shape(%arg0: memref, %sz0: index, %sz1: index) { // expected-error @+1 {{invalid number of reassociation groups: found 1, expected 2}} - %0 = memref.expand_shape %arg0 [[0, 1]] : memref into memref + %0 = memref.expand_shape %arg0 [[0, 1]] output_shape [%sz0, 5, %sz1] : memref into memref return } @@ -402,7 +402,7 @@ func.func @expand_shape(%arg0: memref) { func.func @expand_shape(%arg0: memref) { // expected-error @+1 {{rank 0 memrefs can only be extended/collapsed with/from ones}} - %0 = memref.expand_shape %arg0 [] : memref into memref<1x2xf32> + %0 = memref.expand_shape %arg0 [] output_shape [1, 2] : memref into memref<1x2xf32> return } @@ -415,9 +415,9 @@ func.func @collapse_shape_out_of_bounds(%arg0: memref) { // ----- -func.func @expand_shape_out_of_bounds(%arg0: memref) { +func.func @expand_shape_out_of_bounds(%arg0: memref, %sz0: index) { // expected-error @+1 {{op reassociation index 2 is out of bounds}} - %0 = memref.expand_shape %arg0 [[0, 1, 2]] : memref into memref<4x?xf32> + %0 = memref.expand_shape %arg0 [[0, 1, 2]] output_shape [4, %sz0] : memref into memref<4x?xf32> } // ----- @@ -425,7 +425,7 @@ func.func @expand_shape_out_of_bounds(%arg0: memref) { func.func @expand_shape_invalid_result_layout( %arg0: memref<30x20xf32, strided<[4000, 2], offset: 100>>) { // expected-error @+1 {{expected expanded type to be 'memref<2x15x20xf32, strided<[60000, 4000, 2], offset: 100>>' but found 'memref<2x15x20xf32, strided<[5000, 4000, 2], offset: 100>>'}} - %0 = memref.expand_shape %arg0 [[0, 1], [2]] : + %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [2, 15, 20] : memref<30x20xf32, strided<[4000, 2], offset: 100>> into memref<2x15x20xf32, strided<[5000, 4000, 2], offset: 100>> } @@ -462,7 +462,7 @@ func.func @collapse_shape_invalid_reassociation_expansion(%arg0: memref) // like this. Verify that a sensible error is emitted in this case. func.func @expand_shape_invalid_reassociation(%arg0: memref<2x3x1xf32>) { // expected-error @+1 {{'memref.expand_shape' op has source rank 3 and result rank 2. This is not an expansion (3 > 2)}} - %0 = memref.expand_shape %arg0 [[0], [1], [1]] : + %0 = memref.expand_shape %arg0 [[0], [1], [1]] output_shape [2, 3] : memref<2x3x1xf32> into memref<2x3xf32> } @@ -495,20 +495,10 @@ func.func @collapse_shape_wrong_collapsed_type(%arg0: memref) { // ----- -func.func @expand_shape_illegal_dynamic_memref - (%arg0: memref) -> memref { - // expected-error @+1 {{at most one dimension in a reassociation group may be dynamic}} - %0 = memref.expand_shape %arg0 [[0], [1], [2, 3, 4]] - : memref into memref - return %0 : memref -} - -// ----- - func.func @expand_shape_illegal_static_memref (%arg0: memref<2x3x20xf32>) -> memref<2x3x2x4x5xf32> { // expected-error @+1 {{collapsed dim size (20) must equal reassociation group size (40)}} - %0 = memref.expand_shape %arg0 [[0], [1], [2, 3, 4]] + %0 = memref.expand_shape %arg0 [[0], [1], [2, 3, 4]] output_shape [2, 3, 2, 4, 5] : memref<2x3x20xf32> into memref<2x3x2x4x5xf32> return %0 : memref<2x3x2x4x5xf32> } @@ -525,30 +515,30 @@ func.func @collapse_shape_illegal_static_memref // ----- -func.func @expand_shape_illegal_mixed_memref(%arg0 : memref) +func.func @expand_shape_illegal_mixed_memref(%arg0 : memref, %sz0: index) -> memref { // expected-error @+1 {{collapsed dim (1) must be dynamic if and only if reassociation group is dynamic}} - %0 = memref.expand_shape %arg0 [[0, 1], [2]] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, 5] : memref into memref return %0 : memref } // ----- -func.func @expand_shape_illegal_mixed_memref_2(%arg0 : memref) +func.func @expand_shape_illegal_mixed_memref_2(%arg0 : memref, %sz0: index) -> memref { // expected-error @+1 {{collapsed dim (1) must be dynamic if and only if reassociation group is dynamic}} - %0 = memref.expand_shape %arg0 [[0], [1, 2]] + %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [%sz0, 4, 5] : memref into memref return %0 : memref } // ----- -func.func @expand_shape_invalid_static_dim_size(%arg0 : memref) +func.func @expand_shape_invalid_static_dim_size(%arg0 : memref, %sz0: index) -> memref { // expected-error @+1 {{collapsed dim size (21) must equal reassociation group size (20)}} - %0 = memref.expand_shape %arg0 [[0], [1, 2]] + %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [%sz0, 4, 5] : memref into memref return %0 : memref } diff --git a/mlir/test/Dialect/MemRef/ops.mlir b/mlir/test/Dialect/MemRef/ops.mlir index 2d69904f27db..60fb0ffeee24 100644 --- a/mlir/test/Dialect/MemRef/ops.mlir +++ b/mlir/test/Dialect/MemRef/ops.mlir @@ -106,9 +106,9 @@ func.func @expand_collapse_shape_static( %0 = memref.collapse_shape %arg0 [[0, 1], [2]] : memref<3x4x5xf32> into memref<12x5xf32> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [3, 4, 5] // CHECK-SAME: memref<12x5xf32> into memref<3x4x5xf32> - %r0 = memref.expand_shape %0 [[0, 1], [2]] : + %r0 = memref.expand_shape %0 [[0, 1], [2]] output_shape [3, 4, 5] : memref<12x5xf32> into memref<3x4x5xf32> // CHECK: memref.collapse_shape {{.*}} {{\[}}[0], [1, 2]] @@ -116,9 +116,9 @@ func.func @expand_collapse_shape_static( %1 = memref.collapse_shape %arg0 [[0], [1, 2]] : memref<3x4x5xf32> into memref<3x20xf32> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] output_shape [3, 4, 5] // CHECK-SAME: memref<3x20xf32> into memref<3x4x5xf32> - %r1 = memref.expand_shape %1 [[0], [1, 2]] : + %r1 = memref.expand_shape %1 [[0], [1, 2]] output_shape [3, 4, 5] : memref<3x20xf32> into memref<3x4x5xf32> // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1, 2]] @@ -126,29 +126,29 @@ func.func @expand_collapse_shape_static( %2 = memref.collapse_shape %arg0 [[0, 1, 2]] : memref<3x4x5xf32> into memref<60xf32> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1, 2]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1, 2]] output_shape [3, 4, 5] // CHECK-SAME: memref<60xf32> into memref<3x4x5xf32> - %r2 = memref.expand_shape %2 [[0, 1, 2]] : + %r2 = memref.expand_shape %2 [[0, 1, 2]] output_shape [3, 4, 5] : memref<60xf32> into memref<3x4x5xf32> -// CHECK: memref.expand_shape {{.*}} [] +// CHECK: memref.expand_shape {{.*}} [] output_shape [1, 1] // CHECK-SAME: memref into memref<1x1xf32> - %r5 = memref.expand_shape %arg5 [] : + %r5 = memref.expand_shape %arg5 [] output_shape [1, 1] : memref into memref<1x1xf32> // Reshapes with a custom layout map. -// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] - %l0 = memref.expand_shape %arg3 [[0], [1, 2]] : +// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] output_shape [30, 4, 5] + %l0 = memref.expand_shape %arg3 [[0], [1, 2]] output_shape [30, 4, 5] : memref<30x20xf32, strided<[4000, 2], offset: 100>> into memref<30x4x5xf32, strided<[4000, 10, 2], offset: 100>> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] - %l1 = memref.expand_shape %arg3 [[0, 1], [2]] : +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [2, 15, 20] + %l1 = memref.expand_shape %arg3 [[0, 1], [2]] output_shape [2, 15, 20] : memref<30x20xf32, strided<[4000, 2], offset: 100>> into memref<2x15x20xf32, strided<[60000, 4000, 2], offset: 100>> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] - %r4 = memref.expand_shape %arg4 [[0], [1, 2]] : +// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] output_shape [1, 1, 5] + %r4 = memref.expand_shape %arg4 [[0], [1, 2]] output_shape [1, 1, 5] : memref<1x5xf32, strided<[5, 1], offset: ?>> into memref<1x1x5xf32, strided<[5, 5, 1], offset: ?>> @@ -164,9 +164,9 @@ func.func @expand_collapse_shape_static( memref<2049xi64, strided<[?], offset: ?>> // Reshapes that expand and collapse back a contiguous buffer with some 1's. -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2], [3, 4]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] // CHECK-SAME: memref<3x4x5xf32> into memref<1x3x4x1x5xf32> - %3 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] : + %3 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5]: memref<3x4x5xf32> into memref<1x3x4x1x5xf32> // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1], [2], [3, 4]] @@ -176,15 +176,18 @@ func.func @expand_collapse_shape_static( // Reshapes on tensors. // CHECK: tensor.expand_shape {{.*}}: tensor<3x4x5xf32> into tensor<1x3x4x1x5xf32> - %t0 = tensor.expand_shape %arg1 [[0, 1], [2], [3, 4]] : + %t0 = tensor.expand_shape %arg1 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] : tensor<3x4x5xf32> into tensor<1x3x4x1x5xf32> // CHECK: tensor.collapse_shape {{.*}}: tensor<1x3x4x1x5xf32> into tensor<3x4x5xf32> %rt0 = tensor.collapse_shape %t0 [[0, 1], [2], [3, 4]] : tensor<1x3x4x1x5xf32> into tensor<3x4x5xf32> +// CHECK: tensor.dim %arg2, {{.*}} : tensor<3x?x5xf32> // CHECK: tensor.expand_shape {{.*}}: tensor<3x?x5xf32> into tensor<1x3x?x1x5xf32> - %t1 = tensor.expand_shape %arg2 [[0, 1], [2], [3, 4]] : + %c1 = arith.constant 1 : index + %sz1 = tensor.dim %arg2, %c1 : tensor<3x?x5xf32> + %t1 = tensor.expand_shape %arg2 [[0, 1], [2], [3, 4]] output_shape [1, 3, %sz1, 1, 5] : tensor<3x?x5xf32> into tensor<1x3x?x1x5xf32> // CHECK: tensor.collapse_shape {{.*}}: tensor<1x3x?x1x5xf32> into tensor<1x?x5xf32> @@ -197,15 +200,18 @@ func.func @expand_collapse_shape_static( func.func @expand_collapse_shape_dynamic(%arg0: memref, %arg1: memref>, %arg2: memref>, - %arg3: memref>) { + %arg3: memref>, + %arg4: index, + %arg5: index, + %arg6: index) { // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]] // CHECK-SAME: memref into memref %0 = memref.collapse_shape %arg0 [[0, 1], [2]] : memref into memref -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [%arg4, 4, %arg5] // CHECK-SAME: memref into memref - %r0 = memref.expand_shape %0 [[0, 1], [2]] : + %r0 = memref.expand_shape %0 [[0, 1], [2]] output_shape [%arg4, 4, %arg5] : memref into memref // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]] @@ -214,9 +220,9 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, memref> into memref> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [%arg4, 4, %arg5] // CHECK-SAME: memref> into memref> - %r1 = memref.expand_shape %1 [[0, 1], [2]] : + %r1 = memref.expand_shape %1 [[0, 1], [2]] output_shape [%arg4, 4, %arg5] : memref> into memref> @@ -226,9 +232,9 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, memref> into memref> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [%arg4, 4, %arg5] // CHECK-SAME: memref> into memref> - %r2 = memref.expand_shape %2 [[0, 1], [2]] : + %r2 = memref.expand_shape %2 [[0, 1], [2]] output_shape [%arg4, 4, %arg5] : memref> into memref> @@ -238,9 +244,9 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, memref> into memref> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1]] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1]] output_shape [%arg6, 42] // CHECK-SAME: memref> into memref - %r3 = memref.expand_shape %3 [[0, 1]] : + %r3 = memref.expand_shape %3 [[0, 1]] output_shape [%arg6, 42] : memref> into memref return } @@ -248,12 +254,12 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, func.func @expand_collapse_shape_zero_dim(%arg0 : memref<1x1xf32>, %arg1 : memref) -> (memref, memref<1x1xf32>) { %0 = memref.collapse_shape %arg0 [] : memref<1x1xf32> into memref - %1 = memref.expand_shape %0 [] : memref into memref<1x1xf32> + %1 = memref.expand_shape %0 [] output_shape [1, 1] : memref into memref<1x1xf32> return %0, %1 : memref, memref<1x1xf32> } // CHECK-LABEL: func @expand_collapse_shape_zero_dim // CHECK: memref.collapse_shape %{{.*}} [] : memref<1x1xf32> into memref -// CHECK: memref.expand_shape %{{.*}} [] : memref into memref<1x1xf32> +// CHECK: memref.expand_shape %{{.*}} [] output_shape [1, 1] : memref into memref<1x1xf32> func.func @collapse_shape_to_dynamic (%arg0: memref) -> memref { @@ -270,16 +276,18 @@ func.func @collapse_shape_to_dynamic // CHECK-LABEL: func @expand_collapse_shape_transposed_layout func.func @expand_collapse_shape_transposed_layout( %m0: memref>, - %m1: memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>>) { + %m1: memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>>, + %sz0: index, + %sz1: index) { - %r0 = memref.expand_shape %m0 [[0], [1, 2]] : + %r0 = memref.expand_shape %m0 [[0], [1, 2]] output_shape [%sz0, %sz1, 5] : memref> into memref> %rr0 = memref.collapse_shape %r0 [[0], [1, 2]] : memref> into memref> - %r1 = memref.expand_shape %m1 [[0, 1], [2], [3, 4]] : + %r1 = memref.expand_shape %m1 [[0, 1], [2], [3, 4]] output_shape [2, 2, 5, 2, 3] : memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>> into memref<2x2x5x2x3xf32, strided<[2, 1, ?, 3000, 1000], offset: 0>> %rr1 = memref.collapse_shape %r1 [[0, 1], [2], [3, 4]] : diff --git a/mlir/test/Dialect/MemRef/runtime-verification.mlir b/mlir/test/Dialect/MemRef/runtime-verification.mlir index 4d7fcf6ac7cb..28777a3e8867 100644 --- a/mlir/test/Dialect/MemRef/runtime-verification.mlir +++ b/mlir/test/Dialect/MemRef/runtime-verification.mlir @@ -2,13 +2,14 @@ // CHECK-LABEL: func @expand_shape( // CHECK-SAME: %[[m:.*]]: memref +// CHECK-SAME: %[[sz0:.*]]: index // CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[c5:.*]] = arith.constant 5 : index // CHECK-DAG: %[[dim:.*]] = memref.dim %[[m]], %[[c0]] // CHECK: %[[mod:.*]] = arith.remsi %[[dim]], %[[c5]] // CHECK: %[[cmpi:.*]] = arith.cmpi eq, %[[mod]], %[[c0]] // CHECK: cf.assert %[[cmpi]], "ERROR: Runtime op verification failed -func.func @expand_shape(%m: memref) -> memref { - %0 = memref.expand_shape %m [[0, 1]] : memref into memref +func.func @expand_shape(%m: memref, %sz0: index) -> memref { + %0 = memref.expand_shape %m [[0, 1]] output_shape [%sz0, 5] : memref into memref return %0 : memref } diff --git a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir index edb53fa024c2..c96f9c31443d 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir @@ -12,7 +12,7 @@ // // CHECK-ROUND-LABEL: func.func @sparse_expand( // CHECK-ROUND-SAME: %[[A:.*]]: tensor<100xf64, #sparse{{[0-9]*}}>) -> tensor<10x10xf64, #sparse{{[0-9]*}}> -// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] : tensor<100xf64, #sparse{{[0-9]*}}> into tensor<10x10xf64, #sparse{{[0-9]*}}> +// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] output_shape [10, 10] : tensor<100xf64, #sparse{{[0-9]*}}> into tensor<10x10xf64, #sparse{{[0-9]*}}> // CHECK-ROUND: return %[[E]] : tensor<10x10xf64, #sparse{{[0-9]*}}> // // CHECK-LABEL: func.func @sparse_expand( @@ -39,7 +39,7 @@ // CHECK: return %[[NT1]] : tensor<10x10xf64, #sparse{{[0-9]*}}> // func.func @sparse_expand(%arg0: tensor<100xf64, #SparseVector>) -> tensor<10x10xf64, #SparseMatrix> { - %0 = tensor.expand_shape %arg0 [[0, 1]] : + %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [10, 10] : tensor<100xf64, #SparseVector> into tensor<10x10xf64, #SparseMatrix> return %0 : tensor<10x10xf64, #SparseMatrix> } @@ -94,8 +94,8 @@ func.func @sparse_collapse(%arg0: tensor<10x10xf64, #SparseMatrix>) -> tensor<10 // roundtrip: // // CHECK-ROUND-LABEL: func.func @dynamic_sparse_expand( -// CHECK-ROUND-SAME: %[[A:.*]]: tensor) -> tensor -// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] : tensor into tensor +// CHECK-ROUND-SAME: %[[A:.*]]: tensor, %[[SZ0:.*]]: index) -> tensor +// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] output_shape [%[[SZ0]], 10] : tensor into tensor // CHECK-ROUND: return %[[E]] : tensor // // CHECK-LABEL: func.func @dynamic_sparse_expand( @@ -127,8 +127,8 @@ func.func @sparse_collapse(%arg0: tensor<10x10xf64, #SparseMatrix>) -> tensor<10 // CHECK-NOT: sparse_tensor.convert // CHECK: return %[[NT1]] : tensor // -func.func @dynamic_sparse_expand(%arg0: tensor) -> tensor { - %0 = tensor.expand_shape %arg0 [[0, 1]] : +func.func @dynamic_sparse_expand(%arg0: tensor, %sz0: index) -> tensor { + %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [%sz0, 10] : tensor into tensor return %0 : tensor } diff --git a/mlir/test/Dialect/Tensor/bufferize.mlir b/mlir/test/Dialect/Tensor/bufferize.mlir index 815bc383af95..4f553adcc500 100644 --- a/mlir/test/Dialect/Tensor/bufferize.mlir +++ b/mlir/test/Dialect/Tensor/bufferize.mlir @@ -367,11 +367,14 @@ func.func @tensor.insert(%t1: tensor<5xf32>, %idx1: index, %f: f32) -> tensor<5x // CHECK-LABEL: func @tensor.expand_shape( // CHECK-SAME: %[[t1:.*]]: tensor -func.func @tensor.expand_shape(%t1: tensor) -> tensor<2x?x10xf32> { +func.func @tensor.expand_shape(%t1: tensor, %sz0: index) -> tensor<2x?x10xf32> { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref - // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] [ - // CHECK-SAME: [0, 1], [2]] : memref into memref<2x?x10xf32> - %0 = tensor.expand_shape %t1 [[0, 1], [2]] + // CHECK: %[[C0:.*]] = arith.constant 0 : index + // CHECK: %[[DIM:.*]] = memref.dim %[[m1]], %[[C0]] : memref + // CHECK: %[[C2:.*]] = arith.constant 2 : index + // CHECK: %[[VAL_1:.*]] = arith.divui %[[DIM]], %[[C2]] : index + // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] {{\[\[}}0, 1], [2]] output_shape [2, %[[VAL_1]], 10] : memref into memref<2x?x10xf32> + %0 = tensor.expand_shape %t1 [[0, 1], [2]] output_shape [2, %sz0, 10] : tensor into tensor<2x?x10xf32> // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] @@ -384,14 +387,15 @@ func.func @tensor.expand_shape(%t1: tensor) -> tensor<2x?x10xf32> { // CHECK-LABEL: func @tensor.expand_shape_of_slice( // CHECK-SAME: %[[t1:.*]]: tensor func.func @tensor.expand_shape_of_slice( - %t1: tensor, %o1: index, %s1: index) -> tensor { + %t1: tensor, %o1: index, %s1: index, %sz0: index) -> tensor { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}, 5] [%{{.*}}, 10] [1, 1] : memref to memref> %0 = tensor.extract_slice %t1[%o1, 5][%s1, 10][1, 1] : tensor to tensor - // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [ - // CHECK-SAME: [0, 1], [2, 3]] : memref> into memref> - %1 = tensor.expand_shape %0 [[0, 1], [2, 3]] : + // CHECK: %[[C7:.*]] = arith.constant 7 : index + // CHECK: %[[VAL_1:.*]] = arith.divui %{{.*}}, %[[C7]] : index + // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_1]], 7, 2, 5] : memref> into memref> + %1 = tensor.expand_shape %0 [[0, 1], [2, 3]] output_shape [%sz0, 7, 2, 5] : tensor into tensor // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] // CHECK: return %[[r]] @@ -407,8 +411,8 @@ func.func @tensor.expand_shape_of_scalar_slice( // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}] [1] [1] : memref to memref> %0 = tensor.extract_slice %t1[%o1][1][1] : tensor to tensor - // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [] : memref into memref<1xf32, strided<[1], offset: ?>> - %1 = tensor.expand_shape %0 [] : tensor into tensor<1xf32> + // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [] output_shape [1] : memref into memref<1xf32, strided<[1], offset: ?>> + %1 = tensor.expand_shape %0 [] output_shape [1] : tensor into tensor<1xf32> // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] // CHECK: return %[[r]] return %1 : tensor<1xf32> diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index 751c57eacd7a..145ba8fcd5eb 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -4,7 +4,7 @@ // CHECK-LABEL: expand_shape_identity_fold // CHECK-NEXT: return func.func @expand_shape_identity_fold(%arg0 : tensor<5xf32>) -> tensor<5xf32> { - %0 = tensor.expand_shape %arg0 [[0]] : tensor<5xf32> into tensor<5xf32> + %0 = tensor.expand_shape %arg0 [[0]] output_shape [5] : tensor<5xf32> into tensor<5xf32> return %0 : tensor<5xf32> } @@ -13,7 +13,7 @@ func.func @expand_shape_identity_fold(%arg0 : tensor<5xf32>) -> tensor<5xf32> { // CHECK-LABEL: expand_shape_rank0_identity_fold // CHECK-NEXT: return func.func @expand_shape_rank0_identity_fold(%arg0 : tensor) -> tensor { - %0 = tensor.expand_shape %arg0 [] : tensor into tensor + %0 = tensor.expand_shape %arg0 [] output_shape [] : tensor into tensor return %0 : tensor } @@ -1051,29 +1051,28 @@ func.func @fold_overlapping_insert(%input : tensor, %slice1: tensor<4 // ----- -func.func @compose_expand_of_expand(%arg0 : tensor) +func.func @compose_expand_of_expand(%arg0 : tensor, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> tensor { - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [%arg1, 4, %arg2] : tensor into tensor - %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4]] - : tensor into tensor + %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4]] output_shape [%arg3, 6, 4, %arg4, 5] : tensor into tensor return %1 : tensor } // CHECK-LABEL: compose_expand_of_expand -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] output_shape [%arg3, 6, 4, %arg4, 5] // CHECK-NOT: tensor.expand_shape // ----- func.func @compose_expand_of_expand_of_zero_dim(%arg0 : tensor) -> tensor<1x1x1xf32> { - %0 = tensor.expand_shape %arg0 [] : tensor into tensor<1xf32> - %1 = tensor.expand_shape %0 [[0, 1, 2]] + %0 = tensor.expand_shape %arg0 [] output_shape [1] : tensor into tensor<1xf32> + %1 = tensor.expand_shape %0 [[0, 1, 2]] output_shape [1, 1, 1] : tensor<1xf32> into tensor<1x1x1xf32> return %1 : tensor<1x1x1xf32> } // CHECK-LABEL: compose_expand_of_expand_of_zero_dim -// CHECK: tensor.expand_shape %{{.*}} [] +// CHECK: tensor.expand_shape %{{.*}} [] output_shape [1, 1, 1] // CHECK-SAME: tensor into tensor<1x1x1xf32> // ----- @@ -1093,7 +1092,7 @@ func.func @collapse_of_cast(%t: tensor<8x12x32xf32>) -> tensor { // ----- func.func @fold_collapse_of_expand(%arg0 : tensor<12x4xf32>) -> tensor<12x4xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [3, 4, 4] : tensor<12x4xf32> into tensor<3x4x4xf32> %1 = tensor.collapse_shape %0 [[0, 1], [2]] : tensor<3x4x4xf32> into tensor<12x4xf32> @@ -1104,9 +1103,9 @@ func.func @fold_collapse_of_expand(%arg0 : tensor<12x4xf32>) -> tensor<12x4xf32> // ----- -func.func @fold_collapse_of_expand_dynamic(%arg0 : tensor) +func.func @fold_collapse_of_expand_dynamic(%arg0 : tensor, %arg1: index, %arg2: index) -> tensor { - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [%arg1, 4, %arg2] : tensor into tensor %1 = tensor.collapse_shape %0 [[0, 1], [2]] : tensor into tensor @@ -1121,7 +1120,7 @@ func.func @compose_expand_of_collapse(%arg0 : tensor<2x3x4x5x6x7x8xf32>) -> tensor<24x5x42x8xf32> { %0 = tensor.collapse_shape %arg0 [[0, 1, 2, 3, 4, 5, 6]] : tensor<2x3x4x5x6x7x8xf32> into tensor<40320xf32> - %1 = tensor.expand_shape %0 [[0, 1, 2, 3]] + %1 = tensor.expand_shape %0 [[0, 1, 2, 3]] output_shape [24, 5, 42, 8] : tensor<40320xf32> into tensor<24x5x42x8xf32> return %1 : tensor<24x5x42x8xf32> } @@ -1137,7 +1136,7 @@ func.func @compose_expand_of_collapse_7D(%arg0 : tensor<24x5x42x8xf32>) -> tensor<2x3x4x5x6x7x8xf32> { %0 = tensor.collapse_shape %arg0 [[0, 1, 2, 3]] : tensor<24x5x42x8xf32> into tensor<40320xf32> - %1 = tensor.expand_shape %0 [[0, 1, 2, 3, 4, 5, 6]] + %1 = tensor.expand_shape %0 [[0, 1, 2, 3, 4, 5, 6]] output_shape [2, 3, 4, 5, 6, 7, 8] : tensor<40320xf32> into tensor<2x3x4x5x6x7x8xf32> return %1 : tensor<2x3x4x5x6x7x8xf32> } @@ -1149,16 +1148,16 @@ func.func @compose_expand_of_collapse_7D(%arg0 : tensor<24x5x42x8xf32>) // ----- -func.func @compose_collapse_of_expand(%arg : tensor) +func.func @compose_collapse_of_expand(%arg : tensor, %arg1: index, %arg2: index, %arg3: index) -> tensor { - %0 = tensor.expand_shape %arg [[0], [1], [2, 3]] + %0 = tensor.expand_shape %arg [[0], [1], [2, 3]] output_shape [%arg1, %arg2, %arg3, 1] : tensor into tensor %1 = tensor.collapse_shape %0 [[0, 1], [2, 3]] : tensor into tensor return %1 : tensor } // CHECK-LABEL: func @compose_collapse_of_expand -// CHECK: (%[[ARG:.*]]: tensor) +// CHECK: (%[[ARG:.*]]: tensor, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index) // CHECK-NEXT: tensor.collapse_shape %[[ARG]] // CHECK-SAME: [0, 1], [2] // CHECK-SAME: : tensor into tensor @@ -1167,14 +1166,14 @@ func.func @compose_collapse_of_expand(%arg : tensor) func.func @compose_collapse_of_expand_1D(%arg0 : tensor<2048xf32>) -> tensor<4x512xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3]] + %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3]] output_shape [1, 4, 1, 512] : tensor<2048xf32> into tensor<1x4x1x512xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3]] : tensor<1x4x1x512xf32> into tensor<4x512xf32> return %1 : tensor<4x512xf32> } // CHECK: func @compose_collapse_of_expand_1D -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] output_shape [4, 512] // CHECK-SAME: tensor<2048xf32> into tensor<4x512xf32> // ----- @@ -1183,14 +1182,14 @@ func.func @compose_expand_of_collapse_0_rank_to_expand(%arg0 : tensor<1x1x1xf32> -> tensor<1x1x1x1xf32> { %0 = tensor.collapse_shape %arg0 [] : tensor<1x1x1xf32> into tensor - %1 = tensor.expand_shape %0 [] + %1 = tensor.expand_shape %0 [] output_shape [1, 1, 1, 1] : tensor into tensor<1x1x1x1xf32> return %1 : tensor<1x1x1x1xf32> } // CHECK: func @compose_expand_of_collapse_0_rank_to_expand // CHECK-SAME: %[[ARG0:.+]]: tensor<1x1x1xf32> // CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0], [1], [2, 3] +// CHECK-SAME: {{\[}}[0], [1], [2, 3]] output_shape [1, 1, 1, 1] // CHECK: return %[[RESULT]] // ----- @@ -1199,7 +1198,7 @@ func.func @compose_expand_of_collapse_0_rank_to_collapse(%arg0 : tensor<1x1x1x1x -> tensor<1x1x1xf32> { %0 = tensor.collapse_shape %arg0 [] : tensor<1x1x1x1xf32> into tensor - %1 = tensor.expand_shape %0 [] + %1 = tensor.expand_shape %0 [] output_shape [1, 1, 1] : tensor into tensor<1x1x1xf32> return %1 : tensor<1x1x1xf32> } @@ -1214,8 +1213,8 @@ func.func @compose_expand_of_collapse_0_rank_to_collapse(%arg0 : tensor<1x1x1x1x // CHECK-LABEL: func @zero_rank_reshape_multi func.func @zero_rank_reshape_multi(%arg0: tensor) -> tensor { // CHECK: return %arg0 - %0 = tensor.expand_shape %arg0 [] : tensor into tensor<1xf32> - %1 = tensor.expand_shape %0 [[0, 1]] : tensor<1xf32> into tensor<1x1xf32> + %0 = tensor.expand_shape %arg0 [] output_shape [1] : tensor into tensor<1xf32> + %1 = tensor.expand_shape %0 [[0, 1]] output_shape [1, 1] : tensor<1xf32> into tensor<1x1xf32> %2 = tensor.collapse_shape %1 [] : tensor<1x1xf32> into tensor return %2 : tensor } @@ -1250,7 +1249,7 @@ func.func @compose_collapse_of_collapse_zero_dim(%arg0 : tensor<1x1x1xf32>) // ----- func.func @fold_collapse_of_expand_1D(%arg0 : tensor<4x512xf32>) -> tensor<2048xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2], [3]] + %0 = tensor.expand_shape %arg0 [[0, 1, 2], [3]] output_shape [1, 4, 1, 512] : tensor<4x512xf32> into tensor<1x4x1x512xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2, 3]] : tensor<1x4x1x512xf32> into tensor<2048xf32> @@ -1264,42 +1263,40 @@ func.func @fold_collapse_of_expand_1D(%arg0 : tensor<4x512xf32>) -> tensor<2048x func.func @fold_collapse_of_expand_unit_dims(%arg0 : tensor<2048x1x1xf32>) -> tensor<4x512x1x1xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3], [4], [5]] - : tensor<2048x1x1xf32> into tensor<1x4x1x512x1x1xf32> + %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3], [4], [5]] output_shape [1, 4, 1, 512, 1, 1] : tensor<2048x1x1xf32> into tensor<1x4x1x512x1x1xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3], [4], [5]] : tensor<1x4x1x512x1x1xf32> into tensor<4x512x1x1xf32> return %1 : tensor<4x512x1x1xf32> } // CHECK: func @fold_collapse_of_expand_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3]] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3]] output_shape [4, 512, 1, 1] // CHECK-SAME: tensor<2048x1x1xf32> into tensor<4x512x1x1xf32> // ----- func.func @compose_collapse_of_expand_unit_dims(%arg0 : tensor<2048x1x2048xf32>) -> tensor<4x512x1x512x4xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3, 4], [5], [6, 7, 8]] - : tensor<2048x1x2048xf32> into tensor<1x4x1x512x1x1x512x1x4xf32> + %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3, 4], [5], [6, 7, 8]] output_shape [1, 4, 1, 512, 1, 1, 512, 1, 4] : tensor<2048x1x2048xf32> into tensor<1x4x1x512x1x1x512x1x4xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3, 4], [5], [6, 7], [8]] : tensor<1x4x1x512x1x1x512x1x4xf32> into tensor<4x512x1x512x4xf32> return %1 : tensor<4x512x1x512x4xf32> } // CHECK: func @compose_collapse_of_expand_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3, 4]] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3, 4]] output_shape [4, 512, 1, 512, 4] // CHECK-SAME: tensor<2048x1x2048xf32> into tensor<4x512x1x512x4xf32> // ----- func.func @compose_collapse_of_expand_trailing_unit_dims(%arg0: tensor<2xf32>) -> tensor<2x1xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2]] + %0 = tensor.expand_shape %arg0 [[0, 1, 2]] output_shape [2, 1, 1] : tensor<2xf32> into tensor<2x1x1xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2]] : tensor<2x1x1xf32> into tensor<2x1xf32> return %1 : tensor<2x1xf32> } // CHECK: func @compose_collapse_of_expand_trailing_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] output_shape [2, 1] // CHECK-SAME: tensor<2xf32> into tensor<2x1xf32> // ----- @@ -1321,14 +1318,13 @@ func.func @compose_collapse_of_collapse_unit_dims_dynamic( func.func @fold_collapse_of_expand_trailing_unit_dims(%arg0: tensor<2xf32>) -> tensor<2x1xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2]] - : tensor<2xf32> into tensor<2x1x1xf32> + %0 = tensor.expand_shape %arg0 [[0, 1, 2]] output_shape [2, 1, 1] : tensor<2xf32> into tensor<2x1x1xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2]] : tensor<2x1x1xf32> into tensor<2x1xf32> return %1 : tensor<2x1xf32> } // CHECK: func @fold_collapse_of_expand_trailing_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] output_shape [2, 1] // CHECK-SAME: tensor<2xf32> into tensor<2x1xf32> // ----- @@ -1349,8 +1345,7 @@ func.func @fold_collapse_of_collapse_trailing_unit_dims_dynamic( func.func @fold_collapse_of_expand_trailing_unit_dims(%arg0: tensor<12x42x1x1xf32>) -> tensor<12x42xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1], [2], [3, 4]] - : tensor<12x42x1x1xf32> into tensor<12x42x1x1x1xf32> + %0 = tensor.expand_shape %arg0 [[0], [1], [2], [3, 4]] output_shape [12, 42, 1, 1, 1] : tensor<12x42x1x1xf32> into tensor<12x42x1x1x1xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2, 3, 4]] : tensor<12x42x1x1x1xf32> into tensor<12x42xf32> return %1 : tensor<12x42xf32> @@ -1361,9 +1356,9 @@ func.func @fold_collapse_of_expand_trailing_unit_dims(%arg0: tensor<12x42x1x1xf3 // ----- -func.func @fold_collapse_of_expand_unit_dims_in_middle(%arg0 : tensor) +func.func @fold_collapse_of_expand_unit_dims_in_middle(%arg0 : tensor, %sz0: index, %sz1: index, %sz2: index) -> tensor { - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] output_shape [%sz0, %sz1, 1, %sz2] : tensor into tensor %1 = tensor.collapse_shape %0 [[0], [1, 2, 3]] : tensor into tensor @@ -1378,7 +1373,7 @@ func.func @fold_collapse_of_expand_unit_dims_in_middle(%arg0 : tensor func.func @no_fold_collapse_of_expand_incompatible(%arg0 : tensor<4x6x8xf32>) -> tensor<2x6x16xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3], [4]] + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3], [4]] output_shape [2, 2, 3, 2, 8] : tensor<4x6x8xf32> into tensor<2x2x3x2x8xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2], [3, 4]] : tensor<2x2x3x2x8xf32> into tensor<2x6x16xf32> @@ -1392,7 +1387,7 @@ func.func @no_fold_collapse_of_expand_incompatible(%arg0 : tensor<4x6x8xf32>) func.func @no_fold_collapse_of_expand_empty_expr(%arg0: tensor<3x2x2xf32>) -> tensor<12x1xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] output_shape [3, 2, 2, 1] : tensor<3x2x2xf32> into tensor<3x2x2x1xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3]] : tensor<3x2x2x1xf32> into tensor<12x1xf32> @@ -1401,7 +1396,7 @@ func.func @no_fold_collapse_of_expand_empty_expr(%arg0: tensor<3x2x2xf32>) // CHECK: func @no_fold_collapse_of_expand_empty_expr // CHECK-SAME: %[[ARG0:.+]]: tensor<3x2x2xf32> // CHECK: %[[RARG0:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: [0], [1], [2, 3] +// CHECK-SAME: {{\[}}[0], [1], [2, 3]] output_shape [3, 2, 2, 1] // CHECK: %[[RES:.+]] = tensor.collapse_shape %[[RARG0]] // CHECK-SAME: [0, 1, 2], [3] // CHECK: return %[[RES:.+]] : tensor<12x1xf32> @@ -1410,7 +1405,7 @@ func.func @no_fold_collapse_of_expand_empty_expr(%arg0: tensor<3x2x2xf32>) func.func @reshape_splat_constant_int32() -> tensor<2x4x2xi32> { %c0 = arith.constant dense<42> : tensor<2x8xi32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] : tensor<2x8xi32> into tensor<2x4x2xi32> return %0 : tensor<2x4x2xi32> } @@ -1421,7 +1416,7 @@ func.func @reshape_splat_constant_int32() -> tensor<2x4x2xi32> { // ----- func.func @expand_shape_splat(%arg : f32) -> tensor<2x2x2xf32> { %c0 = tensor.splat %arg : tensor<2x4xf32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 2, 2] : tensor<2x4xf32> into tensor<2x2x2xf32> return %0 : tensor<2x2x2xf32> } @@ -1434,13 +1429,12 @@ func.func @expand_shape_splat(%arg : f32) -> tensor<2x2x2xf32> { // ----- // CHECK-LABEL: @expand_shape_splat_dynamic_no_fold -// CHECK-SAME: %[[F:.+]]: f32 -// CHECK-SAME: %[[M:.+]]: index -func.func @expand_shape_splat_dynamic_no_fold(%arg: f32, %m: index) -> tensor<2x2x?xf32> { - // CHECK: %[[SPLAT:.+]] = tensor.splat %[[F]][%[[M]]] +// CHECK-SAME: (%[[F:.+]]: f32, %[[M:.+]]: index, %[[SZ0:.+]]: index) +func.func @expand_shape_splat_dynamic_no_fold(%arg: f32, %m: index, %sz0: index) -> tensor<2x2x?xf32> { + // CHECK: %[[SPLAT:.+]] = tensor.splat %[[F]][%[[M]]] : tensor<2x?xf32> // CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[SPLAT]] %c0 = tensor.splat %arg[%m] : tensor<2x?xf32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x?xf32> into tensor<2x2x?xf32> + %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 2, %sz0] : tensor<2x?xf32> into tensor<2x2x?xf32> return %0 : tensor<2x2x?xf32> } @@ -1475,7 +1469,7 @@ func.func @collapse_shape_splat_dynamic_no_fold(%f: f32, %m: index) -> tensor<2x func.func @reshape_splat_constant_int16() -> tensor<2x4x2xi16> { %c0 = arith.constant dense<42> : tensor<2x8xi16> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] : tensor<2x8xi16> into tensor<2x4x2xi16> return %0 : tensor<2x4x2xi16> } @@ -1488,7 +1482,7 @@ func.func @reshape_splat_constant_int16() -> tensor<2x4x2xi16> { func.func @reshape_splat_constant_float32() -> tensor<2x4x2xf32> { %c0 = arith.constant dense<42.0> : tensor<2x8xf32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] : tensor<2x8xf32> into tensor<2x4x2xf32> return %0 : tensor<2x4x2xf32> } @@ -1501,7 +1495,7 @@ func.func @reshape_splat_constant_float32() -> tensor<2x4x2xf32> { func.func @reshape_splat_constant_float64() -> tensor<2x4x2xf64> { %c0 = arith.constant dense<42.0> : tensor<2x8xf64> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] : tensor<2x8xf64> into tensor<2x4x2xf64> return %0 : tensor<2x4x2xf64> } @@ -1851,7 +1845,7 @@ func.func @fold_expand_shape_from_elements(%arg0: i32) -> tensor<1xi32> { // CHECK: %[[FROM:.+]] = tensor.from_elements %arg0 : tensor<1xi32> // CHECK: return %[[FROM]] : tensor<1xi32> %0 = tensor.from_elements %arg0 : tensor - %1 = tensor.expand_shape %0 [] : tensor into tensor<1xi32> + %1 = tensor.expand_shape %0 [] output_shape [1] : tensor into tensor<1xi32> return %1 : tensor<1xi32> } @@ -2073,9 +2067,9 @@ func.func @empty_tensor_canonicalize(%i : index) { // CHECK: %[[dim:.*]] = tensor.dim %[[t]], %[[c1]] : tensor // CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[dim]]] // CHECK: return %[[apply]] -func.func @dim_of_expand_shape(%t: tensor) -> index { +func.func @dim_of_expand_shape(%t: tensor, %sz0: index, %sz1: index) -> index { %c2 = arith.constant 2 : index - %0 = tensor.expand_shape %t [[0], [1, 2, 3, 4, 5]] + %0 = tensor.expand_shape %t [[0], [1, 2, 3, 4, 5]] output_shape [%sz0, 1, %sz1, 5, 1, 8] : tensor into tensor %1 = tensor.dim %0, %c2 : tensor return %1 : index @@ -2107,9 +2101,9 @@ func.func @dim_of_collapse_shape(%t: tensor) -> index { // CHECK-LABEL: func @collapse_expand_fold_to_cast( // CHECK-SAME: %[[t:.*]]: tensor // CHECK: return %[[t]] -func.func @collapse_expand_fold_to_cast(%t: tensor) -> (tensor) +func.func @collapse_expand_fold_to_cast(%t: tensor, %sz0: index) -> (tensor) { - %0 = tensor.expand_shape %t [[0, 1]] : tensor into tensor<1x?xf32> + %0 = tensor.expand_shape %t [[0, 1]] output_shape [1, %sz0] : tensor into tensor<1x?xf32> %1 = tensor.collapse_shape %0 [[0, 1]] : tensor<1x?xf32> into tensor return %1 : tensor } diff --git a/mlir/test/Dialect/Tensor/fold-empty-op.mlir b/mlir/test/Dialect/Tensor/fold-empty-op.mlir index 15f841f2128e..e200a4f89261 100644 --- a/mlir/test/Dialect/Tensor/fold-empty-op.mlir +++ b/mlir/test/Dialect/Tensor/fold-empty-op.mlir @@ -13,10 +13,9 @@ module attributes {transform.with_named_sequence} { // CHECK: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 floordiv 28)> // CHECK: #[[$MAP2:.+]] = affine_map<()[s0] -> (s0 * 28)> -func.func @empty_reshape_expansion(%arg0 : index) -> tensor<2x3x5x4x?x7xf32> { +func.func @empty_reshape_expansion(%arg0 : index, %sz0: index) -> tensor<2x3x5x4x?x7xf32> { %0 = tensor.empty(%arg0) : tensor<6x5x?xf32> - %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4, 5]] - : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> + %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4, 5]] output_shape [2, 3, 5, 4, %sz0, 7] : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> return %1 : tensor<2x3x5x4x?x7xf32> } // CHECK-LABEL: func @empty_reshape_expansion diff --git a/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir b/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir index 625408dfefe2..d3ac6ce792f3 100644 --- a/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir +++ b/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir @@ -11,9 +11,11 @@ func.func @expand_shape_of_rank_reducing_extract( { %0 = tensor.extract_slice %t[0, 0, 0, 0][%idx, 1, 1, 5][1, 1, 1, 1] : tensor to tensor - %1 = tensor.expand_shape %0 [[0], [1, 2], [3]] + %c0 = arith.constant 0 : index + %sz0 = tensor.dim %0, %c0 : tensor + %1 = tensor.expand_shape %0 [[0], [1, 2], [3]] output_shape [%sz0, 1, 1, 5] : tensor into tensor - %2 = tensor.expand_shape %0 [[0, 1], [2], [3]] + %2 = tensor.expand_shape %0 [[0, 1], [2], [3]] output_shape [%sz0, 1, 1, 5] : tensor into tensor return %1, %2 : tensor, tensor } diff --git a/mlir/test/Dialect/Tensor/invalid.mlir b/mlir/test/Dialect/Tensor/invalid.mlir index 79ca0de68a1e..3617ed5d61af 100644 --- a/mlir/test/Dialect/Tensor/invalid.mlir +++ b/mlir/test/Dialect/Tensor/invalid.mlir @@ -273,21 +273,10 @@ func.func @insert_slice_wrong_dynamic_type(%t1: tensor, %t2: tensor<8 // ----- -func.func @illegal_expanding_reshape_dynamic_tensor - (%arg0: tensor) -> tensor { - // expected-error @+1 {{invalid to have a single dimension (2) expanded into multiple dynamic dims (2,4)}} - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3, 4]] - : tensor into tensor - return %0 : tensor -} - -// ----- - - func.func @illegal_expanding_reshape_static_tensor (%arg0: tensor<2x3x20xf32>) -> tensor<2x3x2x4x5xf32> { // expected-error @+1 {{expected dimension 2 of collapsed type to be static value of 40}} - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3, 4]] + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3, 4]] output_shape [2, 3, 2, 4, 5] : tensor<2x3x20xf32> into tensor<2x3x2x4x5xf32> return %0 : tensor<2x3x2x4x5xf32> } @@ -304,20 +293,20 @@ func.func @illegal_collapsing_reshape_static_tensor // ----- -func.func @illegal_expanding_reshape_mixed_tensor(%arg0 : tensor) +func.func @illegal_expanding_reshape_mixed_tensor(%arg0 : tensor, %sz0: index) -> tensor { // expected-error @+1 {{expected dimension 1 of collapsed type to be static value of 5}} - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, 5] : tensor into tensor return %0 : tensor } // ----- -func.func @illegal_expanding_reshape_mixed_tensor_2(%arg0 : tensor) +func.func @illegal_expanding_reshape_mixed_tensor_2(%arg0 : tensor, %sz0: index) -> tensor { // expected-error @+1 {{expected dimension 1 of collapsed type to be static value of 20}} - %0 = tensor.expand_shape %arg0 [[0], [1, 2]] + %0 = tensor.expand_shape %arg0 [[0], [1, 2]] output_shape [%sz0, 4, 5] : tensor into tensor return %0 : tensor } diff --git a/mlir/test/Dialect/Tensor/ops.mlir b/mlir/test/Dialect/Tensor/ops.mlir index 2b0a74acce08..378137a14b59 100644 --- a/mlir/test/Dialect/Tensor/ops.mlir +++ b/mlir/test/Dialect/Tensor/ops.mlir @@ -194,12 +194,26 @@ func.func @insert_slice( func.func @tensor_reshape_zero_dim(%arg0 : tensor<1x1xf32>, %arg1 : tensor) -> (tensor, tensor<1x1xf32>) { %0 = tensor.collapse_shape %arg0 [] : tensor<1x1xf32> into tensor - %1 = tensor.expand_shape %0 [] : tensor into tensor<1x1xf32> + %1 = tensor.expand_shape %0 [] output_shape [1, 1] : tensor into tensor<1x1xf32> return %0, %1 : tensor, tensor<1x1xf32> } // CHECK-LABEL: func @tensor_reshape_zero_dim // CHECK: tensor.collapse_shape %{{.*}} [] : tensor<1x1xf32> into tensor -// CHECK: tensor.expand_shape %{{.*}} [] : tensor into tensor<1x1xf32> +// CHECK: tensor.expand_shape %{{.*}} [] output_shape [1, 1] : tensor into tensor<1x1xf32> + +// ----- + +func.func @tensor_expand_shape_dynamic_dim(%arg0 : tensor, %sz0 : index, %sz1 : index, %sz2 : index) + -> (tensor<5x?x?x?xf32>) { + %1 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [5, %sz0, %sz1, %sz2] : tensor into tensor<5x?x?x?xf32> + return %1 : tensor<5x?x?x?xf32> +} + +// CHECK-LABEL: func.func @tensor_expand_shape_dynamic_dim(%arg0: tensor, %arg1: index, %arg2: index, %arg3: index) -> tensor<5x?x?x?xf32> { +// CHECK: %expanded = tensor.expand_shape %arg0 {{\[\[}}0, 1], [2, 3{{\]\]}} output_shape [5, %arg1, %arg2, %arg3] : tensor into tensor<5x?x?x?xf32> +// CHECK: return %expanded : tensor<5x?x?x?xf32> +// CHECK: } + // ----- diff --git a/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir b/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir index 9948c0246e6e..5a2eade0eccc 100644 --- a/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir +++ b/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir @@ -2,7 +2,7 @@ // CHECK-LABEL: func.func @single_dim_packing( // CHECK-SAME: %[[ARG0:.+]]: tensor<256xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] : tensor<256xf32> into tensor<8x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] output_shape [8, 32] : tensor<256xf32> into tensor<8x32xf32> // CHECK: return %[[EXPANDED]] : tensor<8x32xf32> func.func @single_dim_packing(%arg0: tensor<256xf32>) -> tensor<8x32xf32> { %empty = tensor.empty() : tensor<8x32xf32> @@ -27,7 +27,7 @@ func.func @single_dim_packing_with_padding(%arg0: tensor<255xf32>) -> tensor<8x3 // CHECK-LABEL: func.func @single_last_inner_dim_packing( // CHECK-SAME: %[[ARG0:.+]]: tensor<5x256xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<5x256xf32> into tensor<5x8x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] output_shape [5, 8, 32] : tensor<5x256xf32> into tensor<5x8x32xf32> // CHECK: return %[[EXPANDED]] : tensor<5x8x32xf32> func.func @single_last_inner_dim_packing(%arg0: tensor<5x256xf32>) -> tensor<5x8x32xf32> { %empty = tensor.empty() : tensor<5x8x32xf32> @@ -39,7 +39,7 @@ func.func @single_last_inner_dim_packing(%arg0: tensor<5x256xf32>) -> tensor<5x8 // CHECK-LABEL: func.func @pack_1d_with_outer_dims_perm( // CHECK-SAME: %[[ARG0:.+]]: tensor<64xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] : tensor<64xf32> into tensor<2x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] output_shape [2, 32] : tensor<64xf32> into tensor<2x32xf32> // CHECK: return %[[EXPANDED]] : tensor<2x32xf32> func.func @pack_1d_with_outer_dims_perm(%arg0: tensor<64xf32>) -> tensor<2x32xf32> { %empty = tensor.empty() : tensor<2x32xf32> @@ -51,7 +51,7 @@ func.func @pack_1d_with_outer_dims_perm(%arg0: tensor<64xf32>) -> tensor<2x32xf3 // CHECK-LABEL: func.func @single_last_inner_dim_packing_with_identity_outer_dims_perm( // CHECK-SAME: %[[ARG0:.+]]: tensor<5x256xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<5x256xf32> into tensor<5x8x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] output_shape [5, 8, 32] : tensor<5x256xf32> into tensor<5x8x32xf32> // CHECK: return %[[EXPANDED]] : tensor<5x8x32xf32> func.func @single_last_inner_dim_packing_with_identity_outer_dims_perm(%arg0: tensor<5x256xf32>) -> tensor<5x8x32xf32> { %empty = tensor.empty() : tensor<5x8x32xf32> @@ -85,7 +85,7 @@ func.func @single_first_inner_dim_packing(%arg0: tensor<256x5xf32>) -> tensor<8x // CHECK-LABEL: func.func @pack_1x32_to_1x32x1x1 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] output_shape [1, 32, 1, 1] // CHECK: return %[[EXPANDED]] func.func @pack_1x32_to_1x32x1x1(%arg0 : tensor<1x32xf32>) -> tensor<1x32x1x1xf32> { %empty = tensor.empty() : tensor<1x32x1x1xf32> @@ -98,7 +98,7 @@ func.func @pack_1x32_to_1x32x1x1(%arg0 : tensor<1x32xf32>) -> tensor<1x32x1x1xf3 // CHECK-LABEL: func.func @pack_1x32_to_1x16x1x2 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] output_shape [1, 16, 1, 2] // CHECK: return %[[EXPANDED]] func.func @pack_1x32_to_1x16x1x2(%arg0 : tensor<1x32xf32>) -> tensor<1x16x1x2xf32> { %empty = tensor.empty() : tensor<1x16x1x2xf32> @@ -111,7 +111,7 @@ func.func @pack_1x32_to_1x16x1x2(%arg0 : tensor<1x32xf32>) -> tensor<1x16x1x2xf3 // CHECK-LABEL: func.func @pack_32x1_to_16x1x2x1 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] output_shape [1, 16, 2, 1] // CHECK: return %[[EXPANDED]] func.func @pack_32x1_to_16x1x2x1(%arg0 : tensor<32x1xf32>) -> tensor<1x16x2x1xf32> { %empty = tensor.empty() : tensor<1x16x2x1xf32> diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 6c732b8f1349..8c6752edc28d 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -3831,6 +3831,7 @@ cc_library( includes = ["include"], deps = [ ":DialectUtilsIncGen", + ":ArithDialect", ":IR", ":Support", "//llvm:Support", -- GitLab From 8c0341df029d7eb8e60d1e4f49edd3e4af1b1e11 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sun, 21 Apr 2024 14:33:48 +0200 Subject: [PATCH 106/357] Revert "[MLIR] Generalize expand_shape to take shape as explicit input" (#89540) Reverts llvm/llvm-project#69267 this broke some bots. --- .../mlir/Dialect/MemRef/IR/MemRefOps.td | 80 ++--- .../mlir/Dialect/Tensor/IR/TensorOps.td | 79 ++--- .../mlir/Dialect/Utils/ReshapeOpsUtils.h | 58 +--- .../mlir/Dialect/Utils/StaticValueUtils.h | 5 +- .../Conversion/TosaToLinalg/TosaToLinalg.cpp | 1 + mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 16 +- .../Transforms/ConvertConv2DToImg2Col.cpp | 2 +- .../Transforms/DataLayoutPropagation.cpp | 10 +- .../Linalg/Transforms/DropUnitDims.cpp | 13 +- .../Linalg/Transforms/ElementwiseOpFusion.cpp | 67 ++-- .../Linalg/Transforms/SplitReduction.cpp | 1 - .../Dialect/Linalg/Transforms/Transforms.cpp | 8 +- mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 82 +---- .../Transforms/SparseTensorRewriting.cpp | 11 +- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 85 +---- .../BufferizableOpInterfaceImpl.cpp | 3 - .../Transforms/PackAndUnpackPatterns.cpp | 24 +- mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp | 83 +---- mlir/lib/Dialect/Utils/StaticValueUtils.cpp | 7 +- .../expand-then-convert-to-llvm.mlir | 16 +- .../MemRefToLLVM/memref-to-llvm.mlir | 4 +- .../TosaToLinalg/tosa-to-linalg.mlir | 29 +- .../TosaToTensor/tosa-to-tensor.mlir | 114 ++----- ...ot-bufferize-empty-tensor-elimination.mlir | 2 +- .../Linalg/bubble-up-extract-slice-op.mlir | 4 +- mlir/test/Dialect/Linalg/collapse-dim.mlir | 6 +- .../Linalg/convert-conv2d-to-img2col.mlir | 20 +- .../Linalg/data-layout-propagation.mlir | 30 +- .../Dialect/Linalg/drop-unit-extent-dims.mlir | 108 +++---- .../Dialect/Linalg/flatten-elementwise.mlir | 2 +- .../fuse-with-reshape-by-collapsing.mlir | 101 +++--- .../Dialect/Linalg/fusion-push-reshape.mlir | 24 +- .../Linalg/reshape_control_fusion.mlir | 2 +- mlir/test/Dialect/Linalg/reshape_fusion.mlir | 292 ++++++------------ .../resolve-shaped-type-result-dims.mlir | 5 +- .../Linalg/transform-op-split-reduction.mlir | 28 +- .../Linalg/vectorization-with-patterns.mlir | 4 +- mlir/test/Dialect/MemRef/canonicalize.mlir | 35 ++- .../MemRef/expand-strided-metadata.mlir | 16 +- .../Dialect/MemRef/fold-memref-alias-ops.mlir | 22 +- mlir/test/Dialect/MemRef/invalid.mlir | 38 ++- mlir/test/Dialect/MemRef/ops.mlir | 72 ++--- .../Dialect/MemRef/runtime-verification.mlir | 5 +- .../Dialect/SparseTensor/sparse_reshape.mlir | 12 +- mlir/test/Dialect/Tensor/bufferize.mlir | 24 +- mlir/test/Dialect/Tensor/canonicalize.mlir | 112 +++---- mlir/test/Dialect/Tensor/fold-empty-op.mlir | 5 +- .../Tensor/fold-reassociative-reshapes.mlir | 6 +- mlir/test/Dialect/Tensor/invalid.mlir | 21 +- mlir/test/Dialect/Tensor/ops.mlir | 18 +- .../Dialect/Tensor/simplify-pack-unpack.mlir | 14 +- .../llvm-project-overlay/mlir/BUILD.bazel | 1 - 52 files changed, 634 insertions(+), 1193 deletions(-) diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td index 14b8d95ea15b..39e66cd9e6e5 100644 --- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td +++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td @@ -1548,6 +1548,7 @@ def MemRef_ReshapeOp: MemRef_Op<"reshape", [ class MemRef_ReassociativeReshapeOp traits = []> : MemRef_Op, + Arguments<(ins AnyStridedMemRef:$src, IndexListArrayAttr:$reassociation)>, Results<(outs AnyStridedMemRef:$result)>{ code commonExtraClassDeclaration = [{ @@ -1572,6 +1573,10 @@ class MemRef_ReassociativeReshapeOp traits = []> : Value getViewSource() { return getSrc(); } }]; + let assemblyFormat = [{ + $src $reassociation attr-dict `:` type($src) `into` type($result) + }]; + let hasFolder = 1; let hasCanonicalizer = 1; let hasVerifier = 1; @@ -1593,10 +1598,14 @@ def MemRef_ExpandShapeOp : MemRef_ReassociativeReshapeOp<"expand_shape", [ Example: ```mlir - %r = memref.expand_shape %0 [[0, 1], [2]] output_shape [%sz0, %sz1, 32] - : memref into memref + %r = memref.expand_shape %0 [[0, 1], [2]] + : memref into memref ``` + At most one dimension of a reassociation group (e.g., [0, 1] above) may be + dynamic in the result type. Otherwise, the op would be ambiguous, as it + would not be clear how the source dimension is extended. + If an op can be statically proven to be invalid (e.g, an expansion from `memref<10xf32>` to `memref<2x6xf32>`), it is rejected by the verifier. If it cannot statically be proven invalid (e.g., the full example above; it is @@ -1613,80 +1622,41 @@ def MemRef_ExpandShapeOp : MemRef_ReassociativeReshapeOp<"expand_shape", [ there must be a dynamic result dimension in the corresponding reassociation group. Same for strides. - The representation for the output shape supports a partially-static - specification via attributes specified through the `static_output_shape` - argument. A special sentinel value `ShapedType::kDynamic` encodes that the - corresponding entry has a dynamic value. There must be exactly as many SSA - inputs in `output_shape` as there are `ShapedType::kDynamic` entries in - `static_output_shape`. - Note: This op currently assumes that the inner strides are of the source/result layout map are the faster-varying ones. }]; - let arguments = (ins AnyStridedMemRef:$src, IndexListArrayAttr:$reassociation, - Variadic:$output_shape, - DenseI64ArrayAttr:$static_output_shape); - - let assemblyFormat = [{ - $src $reassociation `output_shape` - custom($output_shape, $static_output_shape) attr-dict `:` - type($src) `into` type($result) - }]; - let builders = [ // Builders using ReassociationIndices. OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - "ArrayRef":$outputShape)>, - - // It will infer output shape using inferOutputShape() method. - OpBuilder<(ins "Type":$resultType, "Value":$src, - "ArrayRef":$reassociation)>, - - // Builder using ReassociationExprs. - OpBuilder<(ins "Type":$resultType, "Value":$src, - "ArrayRef":$reassociation), + CArg<"ArrayRef", "{}">:$attrs), [{ - auto reassociationIndices = - convertReassociationMapsToIndices(reassociation); - build($_builder, $_state, resultType, src, reassociationIndices); + build($_builder, $_state, resultType, src, attrs); + $_state.addAttribute("reassociation", + getReassociationIndicesAttribute($_builder, reassociation)); }]>, + // Builder using ReassociationExprs. OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - "ArrayRef":$outputShape), + CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices(reassociation); - build($_builder, $_state, resultType, src, reassociationMaps, - outputShape); + convertReassociationMapsToIndices($_builder, reassociation); + build($_builder, $_state, resultType, src, reassociationMaps, attrs); }]>, - // Builder that infers the result layout map. The result shape must be - // specified. Otherwise, the op may be ambiguous. The output shape for - // the op will be inferred using the inferOutputShape() method. - OpBuilder<(ins "ArrayRef":$resultShape, "Value":$src, - "ArrayRef":$reassociation)>, - // Builder that infers the result layout map. The result shape must be // specified. Otherwise, the op may be ambiguous. OpBuilder<(ins "ArrayRef":$resultShape, "Value":$src, - "ArrayRef":$reassociation, - "ArrayRef":$outputShape)> + "ArrayRef":$reassociation)> ]; let extraClassDeclaration = commonExtraClassDeclaration # [{ static FailureOr computeExpandedType( MemRefType srcType, ArrayRef resultShape, ArrayRef reassociation); - - // Infer the output shape for a memref.expand_shape when it is possible - // to do so. - static FailureOr> inferOutputShape( - OpBuilder &b, Location loc, MemRefType expandedType, - ArrayRef reassociation, - ArrayRef inputShape); }]; let hasVerifier = 1; @@ -1737,12 +1707,6 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ source/result layout map are the faster-varying ones. }]; - let arguments = (ins AnyStridedMemRef:$src, IndexListArrayAttr:$reassociation); - - let assemblyFormat = [{ - $src $reassociation attr-dict `:` type($src) `into` type($result) - }]; - let builders = [ // Builders for a contracting reshape whose result type is computed from // `src` and `reassociation`. @@ -1754,7 +1718,7 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices(reassociation); + convertReassociationMapsToIndices($_builder, reassociation); build($_builder, $_state, src, reassociationMaps, attrs); }]>, @@ -1772,7 +1736,7 @@ def MemRef_CollapseShapeOp : MemRef_ReassociativeReshapeOp<"collapse_shape", [ CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices(reassociation); + convertReassociationMapsToIndices($_builder, reassociation); build($_builder, $_state, resultType, src, reassociationMaps, attrs); }]> ]; diff --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td index a403e89a39f9..cf7f3e89079c 100644 --- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td +++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td @@ -1062,7 +1062,8 @@ class Tensor_ReassociativeReshapeOp traits = []> : Tensor_Op, Pure])>, - Results<(outs AnyTensor:$result)> { + Arguments<(ins AnyRankedTensor:$src, IndexListArrayAttr:$reassociation)>, + Results<(outs AnyRankedTensor:$result)> { code commonExtraClassDeclaration = [{ static StringRef getReassociationAttrStrName() { return "reassociation"; } @@ -1085,6 +1086,10 @@ class Tensor_ReassociativeReshapeOp traits = []> : } }]; + let assemblyFormat = [{ + $src $reassociation attr-dict `:` type($src) `into` type($result) + }]; + let hasFolder = 1; let hasCanonicalizer = 1; let hasVerifier = 1; @@ -1097,75 +1102,43 @@ def Tensor_ExpandShapeOp : Tensor_ReassociativeReshapeOp<"expand_shape"> { rank than the operand `src` whose dimension sizes are a reassociation of `src`. - A reassociation is defined as a continuous grouping of dimensions and is - represented with an array of DenseI64ArrayAttr attribute. The reassociation - maps applied to the result tensor with the higher rank must result in the - operand tensor with the smaller rank. + A reassociation is defined as a continuous grouping of dimensions. It is + represented with an array of DenseI64ArrayAttr attribute. Entries in the + array are referred to as reassociation maps. - The representation for the output shape supports a partially-static - specification via attributes specified through the `static_output_shape` - argument. A special sentinel value `ShapedType::kDynamic` encodes that the - corresponding entry has a dynamic value. There must be exactly as many SSA - inputs in `output_shape` as there are `ShapedType::kDynamic` entries in - `static_output_shape`. + The reassociation maps are applied to the result shape to obtain the operand + shape. Example: ```mlir // Dimension expansion i -> (i', j') and (k) -> (k') - %b = tensor.expand_shape %a [[0, 1], [2]] output_shape [%sz0, %sz1, 32] - : tensor into tensor + %b = tensor.expand_shape %a [[0, 1], [2]] + : tensor into tensor ``` }]; - - let arguments = (ins AnyTensor:$src, IndexListArrayAttr:$reassociation, - Variadic:$output_shape, - DenseI64ArrayAttr:$static_output_shape); - - let assemblyFormat = [{ - $src $reassociation `output_shape` - custom($output_shape, $static_output_shape) attr-dict `:` - type($src) `into` type($result) - }]; - let builders = [ // Builders using ReassociationIndices. OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - "ArrayRef":$outputShape)>, - - // It will infer output shape using inferOutputShape() method. - OpBuilder<(ins "Type":$resultType, "Value":$src, - "ArrayRef":$reassociation)>, - - // Builder using ReassociationExprs. - OpBuilder<(ins "Type":$resultType, "Value":$src, - "ArrayRef":$reassociation), + CArg<"ArrayRef", "{}">:$attrs), [{ - auto reassociationIndices = - convertReassociationMapsToIndices(reassociation); - build($_builder, $_state, resultType, src, reassociationIndices); + build($_builder, $_state, resultType, src, attrs); + $_state.addAttribute("reassociation", + getReassociationIndicesAttribute($_builder, reassociation)); }]>, OpBuilder<(ins "Type":$resultType, "Value":$src, "ArrayRef":$reassociation, - "ArrayRef":$outputShape), + CArg<"ArrayRef", "{}">:$attrs), [{ - auto reassociationIndices = - convertReassociationMapsToIndices(reassociation); - build($_builder, $_state, resultType, src, reassociationIndices, - outputShape); + auto reassociationMaps = + convertReassociationMapsToIndices($_builder, reassociation); + build($_builder, $_state, resultType, src, reassociationMaps, attrs); }]> ]; let extraClassDeclaration = commonExtraClassDeclaration # [{ int64_t getCorrespondingSourceDim(int64_t resultDim); - - // Infer the output shape for a tensor.expand_shape when it is possible - // to do so. - static FailureOr> inferOutputShape( - OpBuilder &b, Location loc, RankedTensorType expandedType, - ArrayRef reassociation, - ArrayRef inputShape); }]; let hasVerifier = 1; @@ -1173,7 +1146,6 @@ def Tensor_ExpandShapeOp : Tensor_ReassociativeReshapeOp<"expand_shape"> { def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { let summary = "operation to produce a tensor with a smaller rank"; - let arguments = (ins AnyTensor:$src, IndexListArrayAttr:$reassociation); let description = [{ The `tensor.collapse_shape` op produces a new tensor of lower (or equal) rank whose dimension sizes are a reassociation of the original `src` dimensions. @@ -1191,11 +1163,6 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { : tensor into tensor ``` }]; - - let assemblyFormat = [{ - $src $reassociation attr-dict `:` type($src) `into` type($result) - }]; - let builders = [ // Builders for a contracting reshape whose result type is computed from // `src` and `reassociation`. @@ -1207,7 +1174,7 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices(reassociation); + convertReassociationMapsToIndices($_builder, reassociation); build($_builder, $_state, src, reassociationMaps, attrs); }]>, @@ -1225,7 +1192,7 @@ def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { CArg<"ArrayRef", "{}">:$attrs), [{ auto reassociationMaps = - convertReassociationMapsToIndices(reassociation); + convertReassociationMapsToIndices($_builder, reassociation); build($_builder, $_state, resultType, src, reassociationMaps, attrs); }]> ]; diff --git a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h index 8a41a0a18b0a..ae9824f728da 100644 --- a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h +++ b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h @@ -30,27 +30,6 @@ using ReassociationExprs = SmallVector; /// Attribute name for the ArrayAttr which encodes reassociation indices. constexpr StringRef getReassociationAttrName() { return "reassociation"; } -// Infer the output shape for a {memref|tensor}.expand_shape when it is possible -// to do so. -// -// Note: This should *only* be used to implement -// `ExpandShapeOp::inferOutputShape` in both the memref and tensor namespaces. -// If you need to infer the output shape you should use the static method of -// `ExpandShapeOp` instead of calling this. -// -// `inputShape` is the shape of the tensor or memref being expanded as a -// sequence of SSA values or constants. `expandedType` is the output shape of -// the expand_shape operation. `reassociation` is the reassociation denoting -// the output dims each input dim is mapped to. -// -// Returns the output shape in `outputShape` and `staticOutputShape`, following -// the conventions for the output_shape and static_output_shape inputs to the -// expand_shape ops. -std::optional> -inferExpandShapeOutputShape(OpBuilder &b, Location loc, ShapedType expandedType, - ArrayRef reassociation, - ArrayRef inputShape); - /// Compose reassociation maps that are used in pair of reshape ops where one /// is a producer and other is the consumer. Only valid to use this method when /// both the producer and consumer are collapsing dimensions or both are @@ -83,7 +62,7 @@ getReassociationIndicesAttribute(OpBuilder &b, /// Convert Array> to Array>. SmallVector convertReassociationMapsToIndices( - ArrayRef reassociationExprs); + OpBuilder &b, ArrayRef reassociationExprs); /// Return the reassociations maps to use to reshape given the source type and /// the target type when possible. Return std::nullopt when this computation @@ -161,11 +140,14 @@ static LogicalResult verifyReshapeLikeTypes(Op op, T expandedType, op.getReassociationIndices(), isExpansion); } -/// Verify that shapes of the reshaped types using following rule: -/// if a dimension in the collapsed type is static, then the corresponding -/// dimensions in the expanded shape should be +/// Verify that shapes of the reshaped types using following rules +/// 1) if a dimension in the collapsed type is static, then the corresponding +/// dimensions in the expanded shape should be /// a) static /// b) the product should be same as the collaped shape. +/// 2) if a dimension in the collaped type is dynamic, one and only one of the +/// corresponding dimensions in the expanded type should be dynamic. This +/// rule is only needed with reshape operations that are expanding. LogicalResult reshapeLikeShapesAreCompatible( function_ref emitError, ArrayRef collapsedShape, ArrayRef expandedShape, @@ -174,11 +156,9 @@ LogicalResult reshapeLikeShapesAreCompatible( /// Returns true iff the type is a MemRefType and has a non-identity layout. bool hasNonIdentityLayout(Type type); -enum class ReshapeOpKind { kExpand, kCollapse }; - /// Pattern to collapse producer/consumer reshape ops that are both collapsing /// dimensions or are both expanding dimensions. -template +template struct ComposeReassociativeReshapeOps : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(ReshapeOpTy reshapeOp, @@ -201,18 +181,8 @@ struct ComposeReassociativeReshapeOps : public OpRewritePattern { rewriter.getContext()); if (!reassociationIndices) return failure(); - - if constexpr (opKind == ReshapeOpKind::kExpand) { - SmallVector outputShape( - getMixedValues(reshapeOp.getStaticOutputShape(), - reshapeOp.getOutputShape(), rewriter)); - rewriter.replaceOpWithNewOp( - reshapeOp, resultType, srcReshapeOp.getSrc(), *reassociationIndices, - outputShape); - } else { - rewriter.replaceOpWithNewOp( - reshapeOp, resultType, srcReshapeOp.getSrc(), *reassociationIndices); - } + rewriter.replaceOpWithNewOp( + reshapeOp, resultType, srcReshapeOp.getSrc(), *reassociationIndices); return success(); } }; @@ -245,8 +215,7 @@ struct ComposeReassociativeReshapeOps : public OpRewritePattern { // /// When `rank(srcType) < rank(resultType)`, then we just swap `reassociation_1` /// `reassociation_2` and produce `expand_shape`. -template +template struct ComposeCollapseOfExpandOp : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(CollapseOpTy collapseOp, @@ -353,11 +322,8 @@ struct ComposeExpandOfCollapseOp : public OpRewritePattern { if (!composedReassociation) return failure(); - SmallVector outputShape(getMixedValues( - expandOp.getStaticOutputShape(), expandOp.getOutputShape(), rewriter)); rewriter.replaceOpWithNewOp( - expandOp, resultType, collapseOp.getSrc(), *composedReassociation, - outputShape); + expandOp, resultType, collapseOp.getSrc(), *composedReassociation); return success(); } diff --git a/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h b/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h index 594bcf5dbb39..20f019666a2e 100644 --- a/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h +++ b/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h @@ -125,8 +125,9 @@ SmallVector getMixedValues(ArrayRef staticValues, /// Decompose a vector of mixed static or dynamic values into the /// corresponding pair of arrays. This is the inverse function of /// `getMixedValues`. -std::pair, SmallVector> -decomposeMixedValues(const SmallVectorImpl &mixedValues); +std::pair> +decomposeMixedValues(Builder &b, + const SmallVectorImpl &mixedValues); /// Helper to sort `values` according to matching `keys`. SmallVector diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp index 7c068d2e94fc..b6b85cab5a38 100644 --- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp +++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp @@ -18,6 +18,7 @@ #include "mlir/Dialect/Math/IR/Math.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" +#include "mlir/Dialect/Tensor/Utils/Utils.h" #include "mlir/Dialect/Tosa/IR/TosaOps.h" #include "mlir/Dialect/Tosa/Utils/ConversionUtils.h" #include "mlir/Dialect/Utils/ReshapeOpsUtils.h" diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp index 6fe0adb955c9..9c5c58fa1fab 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -586,20 +586,12 @@ struct FoldFillWithTensorReshape : OpRewritePattern { return failure(); Location loc = oldFill.getLoc(); - TensorReshapeOp newInit; - if constexpr (std::is_same::value) { - - newInit = rewriter.create( - loc, reshapeOp.getResultType(), oldFill.output(), - reshapeOp.getReassociation(), reshapeOp.getOutputShape(), - reshapeOp.getStaticOutputShape()); - } else { - newInit = rewriter.create(loc, reshapeOp.getResultType(), - oldFill.output(), - reshapeOp.getReassociation()); - } + auto newInit = rewriter.create( + loc, reshapeOp.getResultType(), oldFill.output(), + reshapeOp.getReassociation()); rewriter.replaceOpWithNewOp(reshapeOp, ValueRange{oldFill.value()}, ValueRange{newInit}); + return success(); } }; diff --git a/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp b/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp index 81d44ba04fa1..420b04b3ee28 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/ConvertConv2DToImg2Col.cpp @@ -349,7 +349,7 @@ rewriteInIm2Col(RewriterBase &rewriter, SmallVector batchMatVecReassociationIndice = {{0, 1}, {2, 3}}; - auto batchMatVecResultReshaped = rewriter.create( + Value batchMatVecResultReshaped = rewriter.create( loc, transposedOutputTensor.getType(), batchMatVecResult.getResult(0), batchMatVecReassociationIndice); diff --git a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp index 9a2493a59e01..7fd88dec71d4 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @@ -757,10 +757,7 @@ pushDownUnPackOpThroughExpandShape(tensor::UnPackOp unPackOp, ArrayRef innerDimsPos = unPackOp.getInnerDimsPos(); ArrayRef outerDimsPerm = unPackOp.getOuterDimsPerm(); - auto expandTy = expandOp.getType().dyn_cast(); - if (!expandTy) - return failure(); - ArrayRef dstShape = expandTy.getShape(); + ArrayRef dstShape = expandOp.getType().getShape(); SmallVector reassocIndices = expandOp.getReassociationIndices(); // Project inner tile pos to the dim pos after expanding. For example, if dims @@ -799,8 +796,9 @@ pushDownUnPackOpThroughExpandShape(tensor::UnPackOp unPackOp, nextPos += 1; } - RankedTensorType newExpandType = tensor::PackOp::inferPackedType( - expandTy, innerTileSizes, projectedInnerDimsPos, newOuterDimsPerm); + RankedTensorType newExpandType = + tensor::PackOp::inferPackedType(expandOp.getType(), innerTileSizes, + projectedInnerDimsPos, newOuterDimsPerm); auto newExpandOp = rewriter.create( expandOp.getLoc(), newExpandType, unPackOp.getSource(), newReassocIndices); diff --git a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp index 65efa18af18f..023ea277bcf4 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @@ -23,7 +23,6 @@ #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Tensor/Transforms/Transforms.h" #include "mlir/Dialect/Tensor/Utils/Utils.h" -#include "mlir/Dialect/Utils/ReshapeOpsUtils.h" #include "mlir/IR/AffineExpr.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/BuiltinTypes.h" @@ -273,9 +272,8 @@ expandValue(RewriterBase &rewriter, Location loc, Value result, Value origDest, assert(rankReductionStrategy == ControlDropUnitDims::RankReductionStrategy::ReassociativeReshape && "unknown rank reduction strategy"); - return rewriter - .create(loc, origResultType, result, reassociation) - .getResult(); + return rewriter.create(loc, origResultType, result, + reassociation); } /// Collapse the given `value` so that the type matches the type of @@ -538,10 +536,9 @@ LogicalResult linalg::dropUnitDims(RewriterBase &rewriter, GenericOp genericOp, resultReplacements.push_back(result); continue; } - Value expandedValue = expandValue(rewriter, loc, result, origDest, - reassociations[opOperandIndex], - options.rankReductionStrategy); - resultReplacements.push_back(expandedValue); + resultReplacements.push_back(expandValue(rewriter, loc, result, origDest, + reassociations[opOperandIndex], + options.rankReductionStrategy)); } rewriter.replaceOp(genericOp, resultReplacements); diff --git a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp index bf3a737f1c2b..373e9cfc3ce7 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @@ -625,14 +625,14 @@ LogicalResult ExpansionInfo::compute(LinalgOp linalgOp, return success(); } -/// Expanding the body of a linalg operation requires adaptations of the -/// accessed loop indices. Specifically, access of indices in the original -/// operation need to be replaced with linearizations of indices in the expanded -/// op. That requires the shape of the expanded dimensions to be static (at -/// least all but the most significant). For now check that these are all -/// statically sized. Note that this could be extended to handle dynamic case, -/// but the implementation below uses `affine.apply` which seems to have issues -/// when the shapes are not static. +/// Epanding the body of a linalg operation requires adaptations of the accessed +/// loop indices. Specifically, access of indices in the original operation need +/// to be replaced with linearizations of indices in the expanded op. That +/// requires the shape of the expanded dimensions to be static (at least all but +/// the most significant). For now check that these are all statically sized. +/// Note that this could be extended to handle dynamic case, but the +/// implementation below uses `affine.apply` which seems to have issues when the +/// shapes are not static. static LogicalResult isLinalgOpExpandable(LinalgOp linalgOp, const ExpansionInfo &expansionInfo, PatternRewriter &rewriter) { @@ -750,31 +750,6 @@ static void updateExpandedGenericOpRegion(PatternRewriter &rewriter, } } -/// Checks if a single dynamic dimension expanded into multiple dynamic -/// dimensions. -static LogicalResult -validateDynamicDimExpansion(LinalgOp linalgOp, - const ExpansionInfo &expansionInfo, - PatternRewriter &rewriter) { - for (unsigned i : llvm::seq(0, expansionInfo.getOrigOpNumDims())) { - ArrayRef expandedShape = expansionInfo.getExpandedShapeOfDim(i); - if (expandedShape.size() == 1) - continue; - bool foundDynamic = false; - for (int64_t shape : expandedShape) { - if (ShapedType::isDynamic(shape)) { - if (foundDynamic) { - return rewriter.notifyMatchFailure( - linalgOp, "cannot infer expanded shape with multiple dynamic " - "dims in the same reassociation group"); - } - foundDynamic = true; - } - } - } - return success(); -} - /// Implements the fusion of a tensor.collapse_shape or a tensor.expand_shape op /// and a generic op as explained in `isFusableWithReshapeByExpansion`. Assumes /// that those conditions have been satisfied. @@ -784,8 +759,6 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, PatternRewriter &rewriter) { assert(isFusableWithReshapeByDimExpansion(linalgOp, fusableOpOperand) && "preconditions for fuse operation failed"); - - Location loc = linalgOp.getLoc(); // Check if reshape is expanding or collapsing. auto expandingReshapeOp = dyn_cast(*reshapeOp); auto collapsingReshapeOp = dyn_cast(*reshapeOp); @@ -805,11 +778,6 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, expandedType.getShape(), collapsedType.getShape(), rewriter))) return std::nullopt; - // TODO: With the support of multiple dynamic dims expansion in - // tensor.expand_shape op, this case can be handled. - if (failed(validateDynamicDimExpansion(linalgOp, expansionInfo, rewriter))) - return std::nullopt; - if (failed(isLinalgOpExpandable(linalgOp, expansionInfo, rewriter))) return std::nullopt; @@ -848,13 +816,15 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, /*isExpandingReshape=*/true))) return std::nullopt; expandedOpOperands.push_back(rewriter.create( - loc, expandedOperandType, opOperand->get(), reassociation)); + linalgOp.getLoc(), expandedOperandType, opOperand->get(), + reassociation)); continue; } } expandedOpOperands.push_back(opOperand->get()); } + Location loc = linalgOp.getLoc(); SmallVector outputs; for (OpOperand &opOperand : linalgOp.getDpsInitsMutable()) { AffineMap indexingMap = linalgOp.getMatchingIndexingMap(&opOperand); @@ -873,7 +843,8 @@ fuseWithReshapeByExpansion(LinalgOp linalgOp, Operation *reshapeOp, /*isExpandingReshape=*/true))) return std::nullopt; outputs.push_back(rewriter.create( - loc, expandedOutputType, opOperand.get(), reassociation)); + linalgOp.getLoc(), expandedOutputType, opOperand.get(), + reassociation)); } else { outputs.push_back(opOperand.get()); } @@ -1644,17 +1615,15 @@ FailureOr mlir::linalg::collapseOpIterationDims( op.getIndexingMapMatchingResult(originalResult.value()); SmallVector reassociation = getOperandReassociation(indexingMap, collapsingInfo); - Value result; if (isa(collapsedOpResult.getType())) { - MemRefType expandShapeResultType = MemRefType::get( - originalResultType.getShape(), originalResultType.getElementType()); - result = rewriter.create( - loc, expandShapeResultType, collapsedOpResult, reassociation); + Value result = rewriter.create( + loc, originalResultType, collapsedOpResult, reassociation); + results.push_back(result); } else { - result = rewriter.create( + Value result = rewriter.create( loc, originalResultType, collapsedOpResult, reassociation); + results.push_back(result); } - results.push_back(result); } else { results.push_back(collapsedOpResult); } diff --git a/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp b/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp index 5bfdbc6d0bb5..6559c86c9e0f 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/SplitReduction.cpp @@ -114,7 +114,6 @@ FailureOr mlir::linalg::splitReduction( Type newType = RankedTensorType::get( newShape, cast(operand->get().getType()).getElementType()); - Value newInput = b.create( loc, newType, operand->get(), reassociation); newInputs.push_back(newInput); diff --git a/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp b/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp index 91dfac802ad6..2297bf5e3551 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @@ -329,13 +329,11 @@ FailureOr linalg::lowerPack(RewriterBase &rewriter, /*transposeOp=*/nullptr}; } } - // 5. Expand from the padded result to the stripMinedShape. - auto expandShapeResultType = - RankedTensorType::Builder(packedTensorType).setShape(stripMinedShape); auto reshapeOp = rewriter.create( - loc, expandShapeResultType, padOp.getResult(), - packingMetadata.reassociations); + loc, + RankedTensorType::Builder(packedTensorType).setShape(stripMinedShape), + padOp.getResult(), packingMetadata.reassociations); // 6. Transpose stripMinedShape to packedShape. SmallVector transpPerm = diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp index ced7fdd0a90f..836dcb8f329e 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -2237,44 +2237,6 @@ FailureOr ExpandShapeOp::computeExpandedType( srcType.getMemorySpace()); } -FailureOr> -ExpandShapeOp::inferOutputShape(OpBuilder &b, Location loc, - MemRefType expandedType, - ArrayRef reassociation, - ArrayRef inputShape) { - std::optional> outputShape = - inferExpandShapeOutputShape(b, loc, expandedType, reassociation, - inputShape); - if (!outputShape) - return failure(); - return *outputShape; -} - -void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, - Type resultType, Value src, - ArrayRef reassociation, - ArrayRef outputShape) { - auto [staticOutputShape, dynamicOutputShape] = - decomposeMixedValues(SmallVector(outputShape)); - build(builder, result, resultType.cast(), src, - getReassociationIndicesAttribute(builder, reassociation), - dynamicOutputShape, staticOutputShape); -} - -void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, - Type resultType, Value src, - ArrayRef reassociation) { - SmallVector inputShape = - getMixedSizes(builder, result.location, src); - MemRefType memrefResultTy = resultType.cast(); - FailureOr> outputShape = inferOutputShape( - builder, result.location, memrefResultTy, reassociation, inputShape); - // Failure of this assertion usually indicates presence of multiple - // dynamic dimensions in the same reassociation group. - assert(succeeded(outputShape) && "unable to infer output shape"); - build(builder, result, memrefResultTy, src, reassociation, *outputShape); -} - void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, ArrayRef resultShape, Value src, ArrayRef reassociation) { @@ -2288,20 +2250,6 @@ void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, build(builder, result, *resultType, src, reassociation); } -void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, - ArrayRef resultShape, Value src, - ArrayRef reassociation, - ArrayRef outputShape) { - // Only ranked memref source values are supported. - auto srcType = llvm::cast(src.getType()); - FailureOr resultType = - ExpandShapeOp::computeExpandedType(srcType, resultShape, reassociation); - // Failure of this assertion usually indicates a problem with the source - // type, e.g., could not get strides/offset. - assert(succeeded(resultType) && "could not compute layout"); - build(builder, result, *resultType, src, reassociation, outputShape); -} - LogicalResult ExpandShapeOp::verify() { MemRefType srcType = getSrcType(); MemRefType resultType = getResultType(); @@ -2318,7 +2266,7 @@ LogicalResult ExpandShapeOp::verify() { if (failed(verifyCollapsedShape(getOperation(), srcType.getShape(), resultType.getShape(), getReassociationIndices(), - /*allowMultipleDynamicDimsPerGroup=*/true))) + /*allowMultipleDynamicDimsPerGroup=*/false))) return failure(); // Compute expected result type (including layout map). @@ -2332,28 +2280,14 @@ LogicalResult ExpandShapeOp::verify() { return emitOpError("expected expanded type to be ") << *expectedResultType << " but found " << resultType; - if ((int64_t)getStaticOutputShape().size() != resultType.getRank()) - return emitOpError("expected number of static shape bounds to be equal to " - "the output rank (") - << resultType.getRank() << ") but found " - << getStaticOutputShape().size() << " inputs instead"; - - if ((int64_t)getOutputShape().size() != - llvm::count(getStaticOutputShape(), ShapedType::kDynamic)) - return emitOpError("mismatch in dynamic dims in output_shape and " - "static_output_shape: static_output_shape has ") - << llvm::count(getStaticOutputShape(), ShapedType::kDynamic) - << " dynamic dims while output_shape has " << getOutputShape().size() - << " values"; - return success(); } void ExpandShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add< - ComposeReassociativeReshapeOps, - ComposeExpandOfCollapseOp>(context); + results.add, + ComposeExpandOfCollapseOp>( + context); } /// Compute the layout map after collapsing a given source MemRef type with the @@ -2554,11 +2488,9 @@ public: void CollapseShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add< - ComposeReassociativeReshapeOps, - ComposeCollapseOfExpandOp, - CollapseShapeOpMemRefCastFolder>(context); + results.add, + ComposeCollapseOfExpandOp, + CollapseShapeOpMemRefCastFolder>(context); } OpFoldResult ExpandShapeOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp index a23a1dae449d..02375f54d715 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp @@ -952,15 +952,8 @@ public: auto rtp = getRankedTensorType(op.getResult()); auto denseTp = RankedTensorType::get(rtp.getShape(), rtp.getElementType()); - ReshapeOp reshape; - if constexpr (std::is_same::value) { - reshape = rewriter.create( - loc, denseTp, op.getSrc(), op.getReassociation(), - op.getOutputShape(), op.getStaticOutputShape()); - } else { - reshape = rewriter.create(loc, denseTp, op.getSrc(), - op.getReassociation()); - } + auto reshape = rewriter.create(loc, denseTp, op.getSrc(), + op.getReassociation()); Value convert = rewriter.create(loc, rtp, reshape); rewriter.replaceOp(op, convert); return success(); diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index f2e6e81a044b..3ff41ab22fbc 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -1641,44 +1641,6 @@ int64_t ExpandShapeOp::getCorrespondingSourceDim(int64_t resultDim) { llvm_unreachable("could not find reassociation group"); } -FailureOr> -ExpandShapeOp::inferOutputShape(OpBuilder &b, Location loc, - RankedTensorType expandedType, - ArrayRef reassociation, - ArrayRef inputShape) { - std::optional> outputShape = - inferExpandShapeOutputShape(b, loc, expandedType, reassociation, - inputShape); - if (!outputShape) - return failure(); - return *outputShape; -} - -void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, - Type resultType, Value src, - ArrayRef reassociation, - ArrayRef outputShape) { - auto [staticOutputShape, dynamicOutputShape] = - decomposeMixedValues(SmallVector(outputShape)); - build(builder, result, resultType.cast(), src, - getReassociationIndicesAttribute(builder, reassociation), - dynamicOutputShape, staticOutputShape); -} - -void ExpandShapeOp::build(OpBuilder &builder, OperationState &result, - Type resultType, Value src, - ArrayRef reassociation) { - SmallVector inputShape = - getMixedSizes(builder, result.location, src); - auto tensorResultTy = resultType.cast(); - FailureOr> outputShape = inferOutputShape( - builder, result.location, tensorResultTy, reassociation, inputShape); - // Failure of this assertion usually indicates presence of multiple - // dynamic dimensions in the same reassociation group. - assert(succeeded(outputShape) && "unable to infer output shape"); - build(builder, result, tensorResultTy, src, reassociation, *outputShape); -} - SmallVector CollapseShapeOp::getReassociationMaps() { return getSymbolLessAffineMaps(getReassociationExprs()); } @@ -1762,24 +1724,7 @@ static LogicalResult verifyTensorReshapeOp(TensorReshapeOp op, } LogicalResult ExpandShapeOp::verify() { - auto srcType = getSrcType(); - auto resultType = getResultType(); - - if ((int64_t)getStaticOutputShape().size() != resultType.getRank()) - return emitOpError("expected number of static shape dims to be equal to " - "the output rank (") - << resultType.getRank() << ") but found " - << getStaticOutputShape().size() << " inputs instead"; - - if ((int64_t)getOutputShape().size() != - llvm::count(getStaticOutputShape(), ShapedType::kDynamic)) - return emitOpError("mismatch in dynamic dims in output_shape and " - "static_output_shape: static_output_shape has ") - << llvm::count(getStaticOutputShape(), ShapedType::kDynamic) - << " dynamic dims while output_shape has " << getOutputShape().size() - << " values"; - - return verifyTensorReshapeOp(*this, resultType, srcType); + return verifyTensorReshapeOp(*this, getResultType(), getSrcType()); } LogicalResult CollapseShapeOp::verify() { @@ -1963,25 +1908,23 @@ struct FoldDimOfCollapseShape : public OpRewritePattern { void ExpandShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add< - ComposeReassociativeReshapeOps, - ComposeExpandOfCollapseOp, - FoldReshapeWithConstant, - FoldReshapeWithSplat, - FoldReshapeWithFromElements, FoldDimOfExpandShape, - FoldDimOfCollapseShape>(context); + results.add, + ComposeExpandOfCollapseOp, + FoldReshapeWithConstant, + FoldReshapeWithSplat, + FoldReshapeWithFromElements, FoldDimOfExpandShape, + FoldDimOfCollapseShape>(context); } void CollapseShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add< - ComposeReassociativeReshapeOps, - ComposeCollapseOfExpandOp, - FoldReshapeWithConstant, - FoldReshapeWithSplat, - FoldReshapeWithFromElements, FoldCollapseOfCastOp>( - context); + results + .add, + ComposeCollapseOfExpandOp, + FoldReshapeWithConstant, + FoldReshapeWithSplat, + FoldReshapeWithFromElements, FoldCollapseOfCastOp>( + context); } OpFoldResult ExpandShapeOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp index d078a575f40d..58ea4cc4da3c 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp @@ -338,9 +338,6 @@ struct ExpandShapeOpInterface // Memref result type is inferred by the builder based on reassociation // indices and result shape. - // TODO: Instead of inferring the output shape argument of - // memref.expand_shape op, use output_shape argument of tensor.expand_shape - // op. replaceOpWithNewBufferizedOp( rewriter, op, tensorResultType.getShape(), *buffer, expandShapeOp.getReassociationIndices()); diff --git a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp index 7011ce23b55a..666ac56c6cd5 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp @@ -52,16 +52,12 @@ static LogicalResult isPackOn1D(RewriterBase &rewriter, Operation *op, struct SimplifyPackToExpandShape : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; - FailureOr - insertExpand(RewriterBase &rewriter, Location loc, Value operand, - Type newOperandType, - ArrayRef reassociation) const { + Value insertExpand(RewriterBase &rewriter, Location loc, Value operand, + Type newOperandType, ArrayAttr reassociation) const { if (operand.getType() == newOperandType) return operand; - return rewriter - .create(loc, newOperandType, operand, - reassociation) - .getResult(); + return rewriter.create(loc, newOperandType, operand, + reassociation); } /// Returns success() if it is only packing on the innermost dimension. @@ -100,14 +96,10 @@ struct SimplifyPackToExpandShape : public OpRewritePattern { getReassociationIndicesForReshape(sourceType, destType); if (!reassociation) return failure(); - FailureOr expanded = - insertExpand(rewriter, packOp.getLoc(), packOp.getSource(), destType, - *reassociation); - if (failed(expanded)) { - return rewriter.notifyMatchFailure( - packOp, "unable to expand source of tensor.pack"); - } - rewriter.replaceOp(packOp, *expanded); + Value expanded = insertExpand( + rewriter, packOp.getLoc(), packOp.getSource(), destType, + getReassociationIndicesAttribute(rewriter, *reassociation)); + rewriter.replaceOp(packOp, expanded); return success(); } }; diff --git a/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp b/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp index 6161faf7e30e..41c7af4593c7 100644 --- a/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp +++ b/mlir/lib/Dialect/Utils/ReshapeOpsUtils.cpp @@ -8,7 +8,6 @@ #include "mlir/Dialect/Utils/ReshapeOpsUtils.h" -#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/Builders.h" @@ -17,67 +16,6 @@ using namespace mlir; -std::optional> -mlir::inferExpandShapeOutputShape(OpBuilder &b, Location loc, - ShapedType expandedType, - ArrayRef reassociation, - ArrayRef inputShape) { - - SmallVector outputShapeValues; - SmallVector outputShapeInts; - // For zero-rank inputs, all dims in result shape are unit extent. - if (inputShape.empty()) { - outputShapeInts.resize(expandedType.getRank(), 1); - return getMixedValues(outputShapeInts, outputShapeValues, b); - } - - // Check for all static shapes. - if (expandedType.hasStaticShape()) { - ArrayRef staticShape = expandedType.getShape(); - outputShapeInts.assign(staticShape.begin(), staticShape.end()); - return getMixedValues(outputShapeInts, outputShapeValues, b); - } - - outputShapeInts.resize(expandedType.getRank(), ShapedType::kDynamic); - for (const auto &it : llvm::enumerate(reassociation)) { - ReassociationIndices indexGroup = it.value(); - - int64_t indexGroupStaticSizesProductInt = 1; - bool foundDynamicShape = false; - for (int64_t index : indexGroup) { - int64_t outputDimSize = expandedType.getDimSize(index); - // Cannot infer expanded shape with multiple dynamic dims in the - // same reassociation group! - if (ShapedType::isDynamic(outputDimSize)) { - if (foundDynamicShape) - return std::nullopt; - foundDynamicShape = true; - } else { - outputShapeInts[index] = outputDimSize; - indexGroupStaticSizesProductInt *= outputDimSize; - } - } - if (!foundDynamicShape) - continue; - - int64_t inputIndex = it.index(); - // Call get() under the assumption that we're not casting - // dynamism. - Value indexGroupSize = inputShape[inputIndex].get(); - Value indexGroupStaticSizesProduct = - b.create(loc, indexGroupStaticSizesProductInt); - Value dynamicDimSize = b.createOrFold( - loc, indexGroupSize, indexGroupStaticSizesProduct); - outputShapeValues.push_back(dynamicDimSize); - } - - if ((int64_t)outputShapeValues.size() != - llvm::count(outputShapeInts, ShapedType::kDynamic)) - return std::nullopt; - - return getMixedValues(outputShapeInts, outputShapeValues, b); -} - std::optional> mlir::getReassociationIndicesForReshape(ShapedType sourceType, ShapedType targetType) { @@ -230,7 +168,7 @@ ArrayAttr mlir::getReassociationIndicesAttribute( } SmallVector mlir::convertReassociationMapsToIndices( - ArrayRef reassociationExprs) { + OpBuilder &b, ArrayRef reassociationExprs) { SmallVector reassociationIndices; for (const auto &exprs : reassociationExprs) { ReassociationIndices indices; @@ -292,17 +230,24 @@ LogicalResult mlir::reshapeLikeShapesAreCompatible( ArrayRef reassociationMaps, bool isExpandingReshape) { unsigned expandedDimStart = 0; for (const auto &map : llvm::enumerate(reassociationMaps)) { - bool foundDynamicShape = false; + std::optional dynamicShape; int64_t linearizedStaticShape = 1; - for (const auto &dim : llvm::enumerate( expandedShape.slice(expandedDimStart, map.value().size()))) { - if (ShapedType::isDynamic(dim.value())) - foundDynamicShape = true; - else + if (ShapedType::isDynamic(dim.value())) { + if (isExpandingReshape && dynamicShape) { + return emitError("invalid to have a single dimension (" + + Twine(map.index()) + + ") expanded into multiple dynamic dims (" + + Twine(expandedDimStart + dynamicShape.value()) + + "," + Twine(expandedDimStart + dim.index()) + ")"); + } + dynamicShape = dim.index(); + } else { linearizedStaticShape *= dim.value(); + } } - if (foundDynamicShape) { + if (dynamicShape) { if (!ShapedType::isDynamic(collapsedShape[map.index()])) { return emitError( "expected dimension " + Twine(map.index()) + diff --git a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp index 74a53709592d..1e8197e10944 100644 --- a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp +++ b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp @@ -180,8 +180,9 @@ SmallVector getMixedValues(ArrayRef staticValues, /// Decompose a vector of mixed static or dynamic values into the corresponding /// pair of arrays. This is the inverse function of `getMixedValues`. -std::pair, SmallVector> -decomposeMixedValues(const SmallVectorImpl &mixedValues) { +std::pair> +decomposeMixedValues(Builder &b, + const SmallVectorImpl &mixedValues) { SmallVector staticValues; SmallVector dynamicValues; for (const auto &it : mixedValues) { @@ -192,7 +193,7 @@ decomposeMixedValues(const SmallVectorImpl &mixedValues) { dynamicValues.push_back(it.get()); } } - return {staticValues, dynamicValues}; + return {b.getI64ArrayAttr(staticValues), dynamicValues}; } /// Helper to sort `values` according to matching `keys`. diff --git a/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir index b86103422b07..87d613986c7c 100644 --- a/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir +++ b/mlir/test/Conversion/MemRefToLLVM/expand-then-convert-to-llvm.mlir @@ -453,7 +453,7 @@ func.func @collapse_shape_dynamic_with_non_identity_layout( func.func @expand_shape_static(%arg0: memref<3x4x5xf32>) -> memref<1x3x4x1x5xf32> { // Reshapes that expand a contiguous tensor with some 1's. - %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] + %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] : memref<3x4x5xf32> into memref<1x3x4x1x5xf32> return %0 : memref<1x3x4x1x5xf32> } @@ -510,7 +510,7 @@ func.func @collapse_shape_fold_zero_dim(%arg0 : memref<1x1xf32>) -> memref // ----- func.func @expand_shape_zero_dim(%arg0 : memref) -> memref<1x1xf32> { - %0 = memref.expand_shape %arg0 [] output_shape [1, 1] : memref into memref<1x1xf32> + %0 = memref.expand_shape %arg0 [] : memref into memref<1x1xf32> return %0 : memref<1x1xf32> } @@ -571,13 +571,13 @@ func.func @collapse_shape_dynamic(%arg0 : memref<1x2x?xf32>) -> memref<1x?xf32> // ----- -func.func @expand_shape_dynamic(%arg0 : memref<1x?xf32>, %sz0: index) -> memref<1x2x?xf32> { - %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [1, 2, %sz0]: memref<1x?xf32> into memref<1x2x?xf32> +func.func @expand_shape_dynamic(%arg0 : memref<1x?xf32>) -> memref<1x2x?xf32> { + %0 = memref.expand_shape %arg0 [[0], [1, 2]]: memref<1x?xf32> into memref<1x2x?xf32> return %0 : memref<1x2x?xf32> } // CHECK-LABEL: func.func @expand_shape_dynamic( -// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32>, %[[SZ0:.*]]: index) -> memref<1x2x?xf32> { +// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32>) -> memref<1x2x?xf32> { // CHECK: %[[MEM:.*]] = builtin.unrealized_conversion_cast %[[ARG]] : memref<1x?xf32> to !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_BUFFER:.*]] = llvm.extractvalue %[[MEM]][0] : !llvm.struct<(ptr, ptr, i64, // CHECK: %[[ALIGNED_BUFFER:.*]] = llvm.extractvalue %[[MEM]][1] : !llvm.struct<(ptr, ptr, i64, @@ -614,15 +614,15 @@ func.func @expand_shape_dynamic(%arg0 : memref<1x?xf32>, %sz0: index) -> memref< // ----- func.func @expand_shape_dynamic_with_non_identity_layout( - %arg0 : memref<1x?xf32, strided<[?, ?], offset: ?>>, %sz0: index) -> + %arg0 : memref<1x?xf32, strided<[?, ?], offset: ?>>) -> memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> { - %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [1, 2, %sz0] : + %0 = memref.expand_shape %arg0 [[0], [1, 2]]: memref<1x?xf32, strided<[?, ?], offset: ?>> into memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> return %0 : memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> } // CHECK-LABEL: func.func @expand_shape_dynamic_with_non_identity_layout( -// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32, strided<[?, ?], offset: ?>>, %[[SZ0:.*]]: index) -> memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> { +// CHECK-SAME: %[[ARG:.*]]: memref<1x?xf32, strided<[?, ?], offset: ?>>) -> memref<1x2x?xf32, strided<[?, ?, ?], offset: ?>> { // CHECK: %[[MEM:.*]] = builtin.unrealized_conversion_cast %[[ARG]] : memref<1x?xf32, strided<[?, ?], offset: ?>> to !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_BUFFER:.*]] = llvm.extractvalue %[[MEM]][0] : !llvm.struct<(ptr, ptr, i64, // CHECK: %[[ALIGNED_BUFFER:.*]] = llvm.extractvalue %[[MEM]][1] : !llvm.struct<(ptr, ptr, i64, diff --git a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir index baf9cfe610a5..37999d6fc14a 100644 --- a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir +++ b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir @@ -334,9 +334,9 @@ memref.global "private" @gv4 : memref = dense<1.0> {alignment = 64} // CHECK-LABEL: func @expand_shape_static( // CHECK-SAME: %[[ARG:.*]]: memref<{{.*}}>) func.func @expand_shape_static(%arg0: memref<3x4x5xf32>) -> memref<1x3x4x1x5xf32> { - // CHECK: memref.expand_shape %[[ARG]] {{\[}}[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] + // CHECK: memref.expand_shape %[[ARG]] {{\[}}[0, 1], [2], [3, 4]] // Reshapes that expand a contiguous tensor with some 1's. - %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] + %0 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] : memref<3x4x5xf32> into memref<1x3x4x1x5xf32> return %0 : memref<1x3x4x1x5xf32> } diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir index 03c9fec1c9a8..3ec15221e299 100644 --- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir @@ -348,7 +348,7 @@ func.func @test_add_2d_all_dynamic(%arg0: tensor, %arg1: tensor, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { - // CHECK: %[[ARG0_EXPANDED:.*]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2]] output_shape [1, 3, 4] : tensor<3x4xf32> into tensor<1x3x4xf32> + // CHECK: %[[ARG0_EXPANDED:.*]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2]] : tensor<3x4xf32> into tensor<1x3x4xf32> // CHECK: %[[VAL_0:.*]] = tensor.empty() : tensor<2x3x4xf32> // CHECK: %[[RESULT:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP1]]], iterator_types = ["parallel", "parallel", "parallel"]} ins(%[[ARG0_EXPANDED]], %[[ARG1]] : tensor<1x3x4xf32>, tensor<2x3x4xf32>) outs(%[[VAL_0]] : tensor<2x3x4xf32>) { // CHECK: ^bb0(%[[VAL_1:.*]]: f32, %[[VAL_2:.*]]: f32, %[[VAL_3:.*]]: f32): @@ -871,7 +871,7 @@ func.func @reduce_float(%arg0: tensor<5x4xf32>) -> () { // CHECK: [[RES:%.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield [[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [1, 4] : tensor<4xf32> into tensor<1x4xf32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<4xf32> into tensor<1x4xf32> %0 = tosa.reduce_sum %arg0 {axis = 0 : i32} : (tensor<5x4xf32>) -> tensor<1x4xf32> // CHECK: [[INIT:%.+]] = tensor.empty() : tensor<5xf32> @@ -882,7 +882,7 @@ func.func @reduce_float(%arg0: tensor<5x4xf32>) -> () { // CHECK: [[RES:%.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield [[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [5, 1] : tensor<5xf32> into tensor<5x1xf32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<5xf32> into tensor<5x1xf32> %1 = tosa.reduce_sum %arg0 {axis = 1 : i32} : (tensor<5x4xf32>) -> tensor<5x1xf32> // CHECK: arith.constant 1.0 @@ -920,10 +920,7 @@ func.func @reduce_float_dyn(%arg0: tensor) -> () { // CHECK: %[[RES:.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[RES]] : f32 // CHECK: } - // CHECK: %[[C0_0:.+]] = arith.constant 0 : index - // CHECK: %[[DIM_1:.+]] = tensor.dim %[[REDUCE]], %[[C0_0]] : tensor - // CHECK: %[[C1:.+]] = arith.constant 1 : index - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] output_shape [%[[DIM_1]], 1, 4] : tensor into tensor + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] : tensor into tensor %0 = tosa.reduce_sum %arg0 {axis = 1 : i32} : (tensor) -> tensor return } @@ -941,7 +938,7 @@ func.func @reduce_float_dyn_rank_1(%arg0: tensor) -> () { // CHECK: %[[RES:.+]] = arith.addf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[RES]] : f32 // CHECK: } - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}] output_shape [1] : tensor into tensor<1xf32> + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}] : tensor into tensor<1xf32> %0 = tosa.reduce_sum %arg0 {axis = 0 : i32} : (tensor) -> tensor<1xf32> return } @@ -961,10 +958,7 @@ func.func @reduce_float_dyn_nonzero_batch(%arg0: tensor<5x?x4xf32>) -> () { // CHECK: %[[RES:.+]] = arith.mulf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[RES]] : f32 // CHECK: } - // CHECK: %[[C1_0:.+]] = arith.constant 1 : index - // CHECK: %[[DIM_1:.+]] = tensor.dim %[[REDUCE]], %[[C1_0]] : tensor<5x?xf32> - // CHECK: %[[C1_2:.+]] = arith.constant 1 : index - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] output_shape [5, %[[DIM_1]], 1] : tensor<5x?xf32> into tensor<5x?x1xf32> + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0], [1, 2]] : tensor<5x?xf32> into tensor<5x?x1xf32> %0 = tosa.reduce_prod %arg0 {axis = 2 : i32} : (tensor<5x?x4xf32>) -> tensor<5x?x1xf32> return } @@ -984,10 +978,7 @@ func.func @reduce_float_dyn_multiple(%arg0: tensor) -> () { // CHECK: %[[MAX:.+]] = arith.maximumf %[[ARG1]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[MAX]] : f32 // CHECK: } - // CHECK: %[[C0_0:.+]] = arith.constant 0 : index - // CHECK: %[[DIM_1:.+]] = tensor.dim %[[REDUCE]], %[[C0_0]] : tensor - // CHECK: %[[C1_2:.+]] = arith.constant 1 : index - // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0, 1]] output_shape [%[[DIM_1]], 1] : tensor into tensor + // CHECK: tensor.expand_shape %[[REDUCE]] {{\[}}[0, 1]] : tensor into tensor %0 = tosa.reduce_max %arg0 {axis = 1 : i32} : (tensor) -> tensor return } @@ -1005,7 +996,7 @@ func.func @reduce_int(%arg0: tensor<5x4xi32>) -> () { // CHECK: [[RES:%.+]] = arith.addi %[[ARG1]], %[[ARG2]] : i32 // CHECK: linalg.yield [[RES]] : i32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [1, 4] : tensor<4xi32> into tensor<1x4xi32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<4xi32> into tensor<1x4xi32> %0 = tosa.reduce_sum %arg0 {axis = 0 : i32} : (tensor<5x4xi32>) -> tensor<1x4xi32> // CHECK: [[INIT:%.+]] = tensor.empty() @@ -1016,7 +1007,7 @@ func.func @reduce_int(%arg0: tensor<5x4xi32>) -> () { // CHECK: [[RES:%.+]] = arith.addi %[[ARG1]], %[[ARG2]] : i32 // CHECK: linalg.yield [[RES]] : i32 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [5, 1] : tensor<5xi32> into tensor<5x1xi32> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<5xi32> into tensor<5x1xi32> %1 = tosa.reduce_sum %arg0 {axis = 1 : i32} : (tensor<5x4xi32>) -> tensor<5x1xi32> // CHECK: arith.constant 1 @@ -1052,7 +1043,7 @@ func.func @reduce_bool(%arg0: tensor<5x4xi1>) -> () { // CHECK: [[RES:%.+]] = arith.andi %[[ARG1]], %[[ARG2]] : i1 // CHECK: linalg.yield [[RES]] : i1 // CHECK: } - // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] output_shape [1, 4] : tensor<4xi1> into tensor<1x4xi1> + // CHECK: tensor.expand_shape [[REDUCE]] {{\[}}[0, 1]] : tensor<4xi1> into tensor<1x4xi1> %0 = tosa.reduce_all %arg0 {axis = 0 : i32} : (tensor<5x4xi1>) -> tensor<1x4xi1> // CHECK: arith.constant false diff --git a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir index b8c3d56f21f1..a8a3c42e1684 100644 --- a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir +++ b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir @@ -14,7 +14,7 @@ func.func @test_reshape_0d_same_s2s_explicit(%arg0: tensor) -> tensor // CHECK-LABEL: test_reshape_0d_up_s2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> // CHECK: %[[VAL_1:.*]] = tensor.cast %[[VAL_0]] : tensor<1xf32> to tensor // CHECK: return %[[VAL_1]] : tensor func.func @test_reshape_0d_up_s2d_auto(%arg0: tensor) -> tensor { @@ -26,7 +26,7 @@ func.func @test_reshape_0d_up_s2d_auto(%arg0: tensor) -> tensor { // CHECK-LABEL: test_reshape_0d_up_s2d_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> // CHECK: %[[VAL_1:.*]] = tensor.cast %[[VAL_0]] : tensor<1xf32> to tensor // CHECK: return %[[VAL_1]] : tensor func.func @test_reshape_0d_up_s2d_explicit(%arg0: tensor) -> tensor { @@ -38,7 +38,7 @@ func.func @test_reshape_0d_up_s2d_explicit(%arg0: tensor) -> tensor // CHECK-LABEL: test_reshape_0d_up_s2s_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> // CHECK: return %[[VAL_0]] : tensor<1xf32> func.func @test_reshape_0d_up_s2s_auto(%arg0: tensor) -> tensor<1xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<1xf32> @@ -49,7 +49,7 @@ func.func @test_reshape_0d_up_s2s_auto(%arg0: tensor) -> tensor<1xf32> { // CHECK-LABEL: test_reshape_0d_up_s2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] output_shape [1] : tensor into tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor into tensor<1xf32> // CHECK: return %[[VAL_0]] : tensor<1xf32> func.func @test_reshape_0d_up_s2s_explicit(%arg0: tensor) -> tensor<1xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<1xf32> @@ -83,12 +83,8 @@ func.func @test_reshape_1d_down_s2s_explicit(%arg0: tensor<1xf32>) -> tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %arg0, %[[C0]] : tensor -// CHECK: %[[C2:.*]] = arith.constant 2 : index -// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C2]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] output_shape [2, %[[VAL_0]]] : tensor into tensor<2x?xf32> -// CHECK: return %[[EXPANDED]] : tensor<2x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor into tensor<2x?xf32> +// CHECK: return %[[VAL_0]] : tensor<2x?xf32> func.func @test_reshape_1d_up_d2d_auto(%arg0: tensor) -> tensor<2x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x?xf32> return %0 : tensor<2x?xf32> @@ -98,7 +94,7 @@ func.func @test_reshape_1d_up_d2d_auto(%arg0: tensor) -> tensor<2x?xf32> // CHECK-LABEL: test_reshape_1d_up_s2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<6xf32> -// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] output_shape [2, 3] : tensor<6xf32> into tensor<2x3xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<6xf32> into tensor<2x3xf32> // CHECK: return %[[VAL_0]] : tensor<2x3xf32> func.func @test_reshape_1d_up_s2s_explicit(%arg0: tensor<6xf32>) -> tensor<2x3xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<6xf32>) -> tensor<2x3xf32> @@ -132,12 +128,8 @@ func.func @test_reshape_2d_down_s2s_explicit(%arg0: tensor<2x3xf32>) -> tensor<6 // CHECK-LABEL: test_reshape_2d_same_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C2:.*]] = arith.constant 2 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C2]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [2, %[[DIV]]] : tensor into tensor<2x?xf32> -// CHECK: return %[[EXPANDED]] : tensor<2x?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor into tensor<2x?xf32> +// CHECK: return %[[VAL_1]] : tensor<2x?xf32> func.func @test_reshape_2d_same_d2d_auto(%arg0: tensor) -> tensor<2x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x?xf32> return %0 : tensor<2x?xf32> @@ -148,7 +140,7 @@ func.func @test_reshape_2d_same_d2d_auto(%arg0: tensor) -> tensor<2x?xf // CHECK-LABEL: test_reshape_2d_same_s2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x4xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x4xf32> into tensor<8xf32> -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [4, 2] : tensor<8xf32> into tensor<4x2xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<8xf32> into tensor<4x2xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<4x2xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_2d_same_s2d_auto(%arg0: tensor<2x4xf32>) -> tensor { @@ -161,7 +153,7 @@ func.func @test_reshape_2d_same_s2d_auto(%arg0: tensor<2x4xf32>) -> tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x4xf32> into tensor<8xf32> -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [4, 2] : tensor<8xf32> into tensor<4x2xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<8xf32> into tensor<4x2xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<4x2xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_2d_same_s2d_explicit(%arg0: tensor<2x4xf32>) -> tensor { @@ -174,7 +166,7 @@ func.func @test_reshape_2d_same_s2d_explicit(%arg0: tensor<2x4xf32>) -> tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<3x2xf32> into tensor<6xf32> -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] output_shape [2, 3] : tensor<6xf32> into tensor<2x3xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<6xf32> into tensor<2x3xf32> // CHECK: return %[[VAL_1]] : tensor<2x3xf32> func.func @test_reshape_2d_same_s2s_explicit(%arg0: tensor<3x2xf32>) -> tensor<2x3xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<3x2xf32>) -> tensor<2x3xf32> @@ -186,11 +178,7 @@ func.func @test_reshape_2d_same_s2s_explicit(%arg0: tensor<3x2xf32>) -> tensor<2 // CHECK-LABEL: test_reshape_3d_same_d2d_auto_empty // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2x?xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<3x2x?xf32> into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C0_0:.*]] = arith.constant 0 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C0_0]] : index -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [0, 3, %[[DIV]]] : tensor into tensor<0x3x?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<0x3x?xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<0x3x?xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_auto_empty(%arg0: tensor<3x2x?xf32>) -> tensor { @@ -203,11 +191,7 @@ func.func @test_reshape_3d_same_d2d_auto_empty(%arg0: tensor<3x2x?xf32>) -> tens // CHECK-LABEL: test_reshape_3d_same_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x?x?xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<2x?x?xf32> into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C8:.*]] = arith.constant 8 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C8]] : index -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [2, %[[DIV]], 4] : tensor into tensor<2x?x4xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<2x?x4xf32> // CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<2x?x4xf32> to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_auto(%arg0: tensor<2x?x?xf32>) -> tensor { @@ -220,11 +204,7 @@ func.func @test_reshape_3d_same_d2d_auto(%arg0: tensor<2x?x?xf32>) -> tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C6:.*]] = arith.constant 6 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C6]] : index -// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [2, 3, %[[DIV]]] : tensor into tensor<2x3x?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<2x3x?xf32> // CHECK: return %[[VAL_1]] : tensor<2x3x?xf32> func.func @test_reshape_3d_same_d2d_auto_identity(%arg0: tensor) -> tensor<2x3x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x3x?xf32> @@ -236,12 +216,8 @@ func.func @test_reshape_3d_same_d2d_auto_identity(%arg0: tensor) -> t // CHECK-LABEL: test_reshape_3d_same_d2d_explicit_empty // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2x?xf32> // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<3x2x?xf32> into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C6:.*]] = arith.constant 6 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C6]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [%[[DIV]], 3, 2] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_explicit_empty(%arg0: tensor<3x2x?xf32>) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<3x2x?xf32>) -> tensor @@ -253,12 +229,8 @@ func.func @test_reshape_3d_same_d2d_explicit_empty(%arg0: tensor<3x2x?xf32>) -> // CHECK-LABEL: test_reshape_3d_same_d2d_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C12:.*]] = arith.constant 12 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C12]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [%[[DIV]], 3, 4] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor // CHECK: return %[[VAL_2]] : tensor func.func @test_reshape_3d_same_d2d_explicit(%arg0: tensor) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor @@ -281,12 +253,8 @@ func.func @test_reshape_3d_same_d2d_explicit_identity(%arg0: tensor) // CHECK-LABEL: test_reshape_3d_same_d2s_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C8:.*]] = arith.constant 8 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C8]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [2, %[[DIV]], 4] : tensor into tensor<2x?x4xf32> -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor<2x?x4xf32> to tensor<2x3x4xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor<2x?x4xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<2x?x4xf32> to tensor<2x3x4xf32> // CHECK: return %[[VAL_2]] : tensor<2x3x4xf32> func.func @test_reshape_3d_same_d2s_auto(%arg0: tensor) -> tensor<2x3x4xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x3x4xf32> @@ -298,12 +266,8 @@ func.func @test_reshape_3d_same_d2s_auto(%arg0: tensor) -> tensor<2x3 // CHECK-LABEL: test_reshape_3d_same_d2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor // CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor -// CHECK: %[[C12:.*]] = arith.constant 12 : index -// CHECK: %[[DIV:.*]] = arith.divui %[[DIM]], %[[C12]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] output_shape [%[[DIV]], 3, 4] : tensor into tensor -// CHECK: %[[VAL_2:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor<2x3x4xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor<2x3x4xf32> // CHECK: return %[[VAL_2]] : tensor<2x3x4xf32> func.func @test_reshape_3d_same_d2s_explicit(%arg0: tensor) -> tensor<2x3x4xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor<2x3x4xf32> @@ -324,14 +288,10 @@ func.func @test_reshape_3d_same_s2s_explicit_identity(%arg0: tensor<2x3x4xf32>) // CHECK-LABEL: test_reshape_3d_up_d2s_explicit // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[COLLAPSED:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[COLLAPSED]], %[[C0]] : tensor -// CHECK: %[[C6:.*]] = arith.constant 6 : index -// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C6]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[COLLAPSED]] {{\[\[}}0, 1, 2, 3]] output_shape [%[[VAL_0]], 3, 2, 1] : tensor into tensor -// CHECK: %[[CAST:.*]] = tensor.cast %[[EXPANDED]] : tensor to tensor<1x3x2x1xf32> -// CHECK: return %[[CAST]] : tensor<1x3x2x1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2, 3]] : tensor into tensor +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor to tensor<1x3x2x1xf32> +// CHECK: return %[[VAL_2]] : tensor<1x3x2x1xf32> func.func @test_reshape_3d_up_d2s_explicit(%input: tensor) -> tensor<1x3x2x1xf32> { %0 = tosa.reshape %input {new_shape = array} : (tensor) -> tensor<1x3x2x1xf32> return %0 : tensor<1x3x2x1xf32> @@ -353,13 +313,9 @@ func.func @test_reshape_4d_down_d2s_explicit(%arg0: tensor) -> tens // CHECK-LABEL: test_reshape_5d_down_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[COLLAPSED:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4]] : tensor into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[COLLAPSED]], %[[C0]] : tensor -// CHECK: %[[C6:.*]] = arith.constant 6 : index -// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C6]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[COLLAPSED]] {{\[\[}}0, 1, 2]] output_shape [%[[VAL_0]], 2, 3] : tensor into tensor -// CHECK: return %[[EXPANDED]] : tensor +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4]] : tensor into tensor +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: return %[[VAL_1]] : tensor func.func @test_reshape_5d_down_d2d_auto(%arg0: tensor) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor) -> tensor return %0 : tensor @@ -369,13 +325,9 @@ func.func @test_reshape_5d_down_d2d_auto(%arg0: tensor) -> tensor // CHECK-LABEL: test_reshape_6d_down_d2d_auto // CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<1x2x?x5x7x11xf32> -// CHECK: %[[COLLAPSED:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4, 5]] : tensor<1x2x?x5x7x11xf32> into tensor -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[DIM:.*]] = tensor.dim %[[COLLAPSED]], %[[C0]] : tensor -// CHECK: %[[C385:.*]] = arith.constant 385 : index -// CHECK: %[[VAL_0:.*]] = arith.divui %[[DIM]], %[[C385]] : index -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[COLLAPSED]] {{\[\[}}0, 1, 2]] output_shape [%[[VAL_0]], 5, 77] : tensor into tensor -// CHECK: return %[[EXPANDED]] : tensor +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4, 5]] : tensor<1x2x?x5x7x11xf32> into tensor +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor into tensor +// CHECK: return %[[VAL_1]] : tensor func.func @test_reshape_6d_down_d2d_auto(%arg0: tensor<1x2x?x5x7x11xf32>) -> tensor { %0 = "tosa.reshape"(%arg0) {new_shape = array} : (tensor<1x2x?x5x7x11xf32>) -> tensor return %0 : tensor diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir index efe59af97d96..9a3e14b6d391 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir @@ -132,7 +132,7 @@ func.func @shape_mismatch(%t: tensor<5x6x128xf32>) -> tensor<5x6x128xf32> { %cst = arith.constant 8.0 : f32 %0 = tensor.empty() : tensor<128xf32> %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<128xf32>) -> tensor<128xf32> - %2 = tensor.expand_shape %1 [[0, 1, 2]] output_shape [1, 1, 128] + %2 = tensor.expand_shape %1 [[0, 1, 2]] : tensor<128xf32> into tensor<1x1x128xf32> %3 = tensor.insert_slice %2 into %t[2, 3, 0][1, 1, 128][1, 1, 1] : tensor<1x1x128xf32> into tensor<5x6x128xf32> diff --git a/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir b/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir index 4bf81820f0e8..0e353a1fa43f 100644 --- a/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir +++ b/mlir/test/Dialect/Linalg/bubble-up-extract-slice-op.mlir @@ -165,9 +165,7 @@ func.func @rank_reducing_slice(%width : index) -> tensor<1x1x1x?xf32> { %init = tensor.empty(%width) : tensor<1x?xf32> %fill = linalg.fill ins(%cst : f32) outs(%init : tensor<1x?xf32>) -> tensor<1x?xf32> %slice = tensor.extract_slice %fill[0, 0] [1, %width] [1, 1] : tensor<1x?xf32> to tensor - %c0 = arith.constant 0 : index - %sz0 = tensor.dim %slice, %c0 : tensor - %expand = tensor.expand_shape %slice [[0, 1, 2, 3]] output_shape [1, 1, 1, %sz0] : tensor into tensor<1x1x1x?xf32> + %expand = tensor.expand_shape %slice [[0, 1, 2, 3]] : tensor into tensor<1x1x1x?xf32> return %expand : tensor<1x1x1x?xf32> } diff --git a/mlir/test/Dialect/Linalg/collapse-dim.mlir b/mlir/test/Dialect/Linalg/collapse-dim.mlir index 61bedecbdca5..547320f53387 100644 --- a/mlir/test/Dialect/Linalg/collapse-dim.mlir +++ b/mlir/test/Dialect/Linalg/collapse-dim.mlir @@ -52,7 +52,7 @@ func.func @collapse_parallel( // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"]} // CHECK-SAME: ins(%[[S]] : tensor<32x2x40960xf32>) outs(%[[D]] : tensor<2x32x40960xf32>) { // CHECK: } -> tensor<2x32x40960xf32> -// CHECK: tensor.expand_shape %[[R]] {{\[}}[0], [1], [2, 3]] output_shape [2, 32, 10, 4096] : tensor<2x32x40960xf32> into tensor<2x32x10x4096xf32> +// CHECK: tensor.expand_shape %[[R]] {{\[}}[0], [1], [2, 3]] : tensor<2x32x40960xf32> into tensor<2x32x10x4096xf32> // ----- @@ -127,8 +127,8 @@ func.func @uncollapsable_strided_memref(%arg0: memref<2x6x24x48xi32>, %arg1: mem // CHECK: %[[VAL_4:.*]] = tensor.collapse_shape %[[VAL_2]] {{\[\[}}0], [1], [2, 3]] : tensor<1x2x12x5xf32> into tensor<1x2x60xf32> // CHECK: %[[VAL_5:.*]] = tensor.collapse_shape %[[VAL_3]] {{\[\[}}0], [1], [2, 3]] : tensor<1x2x12x5xf32> into tensor<1x2x60xf32> // CHECK: %[[VAL_6:.*]] = linalg.copy ins(%[[VAL_4]] : tensor<1x2x60xf32>) outs(%[[VAL_5]] : tensor<1x2x60xf32>) -> tensor<1x2x60xf32> -// CHECK: %[[VAL_7:.*]] = tensor.expand_shape %[[VAL_6]] {{\[\[}}0], [1], [2, 3]] output_shape [1, 2, 12, 5] : tensor<1x2x60xf32> into tensor<1x2x12x5xf32> -// CHECK: %[[VAL_8:.*]] = tensor.expand_shape %[[VAL_7]] {{\[\[}}0], [1], [2, 3], [4]] output_shape [1, 2, 3, 4, 5] : tensor<1x2x12x5xf32> into tensor<1x2x3x4x5xf32, 3 : i64> +// CHECK: %[[VAL_7:.*]] = tensor.expand_shape %[[VAL_6]] {{\[\[}}0], [1], [2, 3]] : tensor<1x2x60xf32> into tensor<1x2x12x5xf32> +// CHECK: %[[VAL_8:.*]] = tensor.expand_shape %[[VAL_7]] {{\[\[}}0], [1], [2, 3], [4]] : tensor<1x2x12x5xf32> into tensor<1x2x3x4x5xf32, 3 : i64> // CHECK: return %[[VAL_8]] : tensor<1x2x3x4x5xf32, 3 : i64> // CHECK: } diff --git a/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir b/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir index c7c846d7ecc9..a64319963531 100644 --- a/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir +++ b/mlir/test/Dialect/Linalg/convert-conv2d-to-img2col.mlir @@ -50,7 +50,7 @@ module attributes {transform.with_named_sequence} { // CHECK: linalg.yield %[[EXTRACTED_INPUT]] : f32 // CHECK: IR printer: transformed -// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d3)> @@ -78,7 +78,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<1x196x16xf32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK: return %[[RESULT]] func.func @conv_16433136(%arg0: tensor<1x16x16x4xf32>, %arg1: tensor<3x3x4x16xf32>, %arg2: tensor<1x14x14x16xf32>) -> tensor<1x14x14x16xf32> { @@ -204,7 +204,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<8x196x16xf32> -// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1, 2], [3]] output_shape [8, 14, 14, 16] : tensor<8x196x16xf32> into tensor<8x14x14x16xf32> +// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1, 2], [3]] : tensor<8x196x16xf32> into tensor<8x14x14x16xf32> // CHECK: return %[[CS_FINAL]] func.func @batch_nhwc_conv(%arg0: tensor<8x16x16x4xf32>, %arg1: tensor<3x3x4x16xf32>, %arg2: tensor<8x14x14x16xf32>) -> tensor<8x14x14x16xf32> { %0 = linalg.conv_2d_nhwc_hwcf @@ -269,7 +269,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<8x16x196xf32> -// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1], [2, 3]] output_shape [8, 16, 14, 14] : tensor<8x16x196xf32> into tensor<8x16x14x14xf32> +// CHECK: %[[CS_FINAL:.+]] = tensor.expand_shape %[[MATMUL]] {{\[}}[0], [1], [2, 3]] : tensor<8x16x196xf32> into tensor<8x16x14x14xf32> // CHECK: return %[[CS_FINAL]] func.func @batch_nchw_conv(%arg0: tensor<8x4x16x16xf32>, %arg1: tensor<16x4x3x3xf32>, %arg2: tensor<8x16x14x14xf32>) -> tensor<8x16x14x14xf32> { %0 = linalg.conv_2d_nchw_fchw @@ -310,7 +310,7 @@ module attributes {transform.with_named_sequence} { // CHECK: linalg.yield %[[EXTRACTED_INPUT]] : f32 // CHECK: IR printer: transformed -// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: tensor.expand_shape %{{[^ ]*}} {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d3)> @@ -338,7 +338,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addf %[[MUL]], %[[ARG2]] : f32 // CHECK: linalg.yield %[[ADD]] : f32 // CHECK: } -> tensor<1x196x16xf32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xf32> into tensor<1x14x14x16xf32> // CHECK: return %[[RESULT]] func.func @conv_2d_nhwc_fhwc(%arg0: tensor<1x16x16x4xf32>, %arg1: tensor<16x3x3x4xf32>, %arg2: tensor<1x14x14x16xf32>) -> tensor<1x14x14x16xf32> { @@ -378,7 +378,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = arith.addi %[[MUL]], %[[ARG2]] : i32 // CHECK: linalg.yield %[[ADD]] : i32 // CHECK: } -> tensor<1x196x16xi32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xi32> into tensor<1x14x14x16xi32> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xi32> into tensor<1x14x14x16xi32> // CHECK: return %[[RESULT]] func.func @conv_integer_extend(%arg0: tensor<1x16x16x4xi8>, %arg1: tensor<3x3x4x16xi8>, %arg2: tensor<1x14x14x16xi32>) -> tensor<1x14x14x16xi32> { @@ -416,7 +416,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = complex.add %[[MUL]], %[[ARG2]] : complex // CHECK: linalg.yield %[[ADD]] : complex // CHECK: } -> tensor<1x196x16xcomplex> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> // CHECK: return %[[RESULT]] func.func @conv_complex(%arg0: tensor<1x16x16x4xcomplex>, %arg1: tensor<3x3x4x16xcomplex>, %arg2: tensor<1x14x14x16xcomplex>) -> tensor<1x14x14x16xcomplex> { @@ -459,7 +459,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = complex.add %[[MUL]], %[[ARG2]] : complex // CHECK: linalg.yield %[[ADD]] : complex // CHECK: } -> tensor<1x196x16xcomplex> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> // CHECK: return %[[RESULT]] func.func @conv_complex_extended(%arg0: tensor<1x16x16x4xcomplex>, %arg1: tensor<3x3x4x16xcomplex>, %arg2: tensor<1x14x14x16xcomplex>) -> tensor<1x14x14x16xcomplex> { @@ -500,7 +500,7 @@ module attributes {transform.with_named_sequence} { // CHECK: %[[ADD:.+]] = complex.add %[[MUL]], %[[ARG2]] : complex // CHECK: linalg.yield %[[ADD]] : complex // CHECK: } -> tensor<1x196x16xcomplex> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] output_shape [1, 14, 14, 16] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[MATMUL_RESULT]] {{\[}}[0], [1, 2], [3]] : tensor<1x196x16xcomplex> into tensor<1x14x14x16xcomplex> // CHECK: return %[[RESULT]] func.func @conv_complex_f16_extended(%arg0: tensor<1x16x16x4xcomplex>, %arg1: tensor<3x3x4x16xf16>, %arg2: tensor<1x14x14x16xcomplex>) -> tensor<1x14x14x16xcomplex> { diff --git a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir index bee08503298f..79d61ab757e3 100644 --- a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir +++ b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir @@ -988,20 +988,17 @@ func.func @no_bubble_up_pack_through_non_divisible_collapse(%1: tensor<3072x64x4 // ----- -func.func @push_down_unpack_through_expand(%5: tensor, %dim: index, %sz0: index) -> tensor { +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]] output_shape [%sz0, 256, 256] : tensor into 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: %[[C32:.+]] = arith.constant 32 : index // CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM0:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[SZ0:.+]] = arith.divui %[[DIM0]], %[[C32]] : index -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3], [4]] output_shape [%[[SZ0]], 32, 32, 8, 8] : tensor into tensor +// 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 @@ -1012,12 +1009,12 @@ func.func @push_down_unpack_through_expand(%5: tensor, %dim: index 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]] output_shape [4, 12, 256, 256] : tensor<4x3072x256xf32> into tensor<4x12x256x256xf32> + %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]] output_shape [4, 32, 12, 32, 8, 8] : tensor<4x32x384x8x8xf32> into tensor<4x32x12x32x8x8xf32> +// 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> @@ -1027,32 +1024,29 @@ func.func @push_down_permuted_unpack_through_expand(%5: tensor<4x32x384x8x8xf32> 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]] output_shape [3, 16, 1, 256] : tensor<48x256xf32> into tensor<3x16x1x256xf32> + %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]] output_shape [3, 2, 1, 32, 8, 8] : tensor<6x32x8x8xf32> into tensor<3x2x1x32x8x8xf32> +// 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, %sz0: index) -> tensor { +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]] output_shape [%sz0, 256, 256] : tensor into 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: %[[C256:.+]] = arith.constant 256 : index // CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM0:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[SZ0:.+]] = arith.divui %[[DIM0]], %[[C256]] : index -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3]] output_shape [%[[SZ0]], 256, 32, 8] : tensor into tensor +// 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 @@ -1063,11 +1057,11 @@ func.func @push_down_unpack_through_expand_on_outer_dims(%5: 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]] output_shape [256, 12, 256] : tensor<3072x256xf32> into tensor<256x12x256xf32> + %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]] output_shape [256, 12, 256] : tensor<3072x256xf32> into tensor<256x12x256xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[UNPACK]] {{\[}}[0, 1], [2]] : tensor<3072x256xf32> into tensor<256x12x256xf32> // CHECK: return %[[EXPANDED]] : tensor<256x12x256xf32> diff --git a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir index a9cbaaf7fdc4..c140b6abcc37 100644 --- a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir +++ b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir @@ -25,22 +25,13 @@ func.func @drop_one_trip_loops(%arg0 : tensor, %arg1 : f32, %shape: t // CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1, d2) -> (d0, d2)> // CHECK-DAG: #[[$MAP2:.*]] = affine_map<(d0, d1, d2) -> ()> // CHECK-DAG: #[[$MAP3:.*]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> -// CHECK-DAG: #[[$MAP4:.*]] = affine_map<()[s0, s1] -> (s0 * s1)> // CHECK-LABEL: func @drop_one_trip_loops -// CHECK: %[[C2:.*]] = arith.constant 2 : index -// CHECK: %[[C1:.*]] = arith.constant 1 : index -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: tensor.collapse_shape %{{.*}} {{\[\[}}0, 1], [2]] -// CHECK: tensor.collapse_shape %{{.*}} {{\[\[}}0, 1], [2, 3], [4]] +// CHECK: tensor.collapse_shape %{{.*}} {{\[}}[0, 1], [2]] +// CHECK: tensor.collapse_shape %{{.*}} {{\[}}[0, 1], [2, 3], [4]] // CHECK: linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP1]], #[[$MAP2]], #[[$MAP3]]] // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"] -// CHECK: %[[DIM:.*]] = tensor.dim %{{.*}}, %[[C0]] -// CHECK: %[[VAL_1:.*]] = affine.apply #[[$MAP4]]()[%[[DIM]], %[[C1]]] -// CHECK: %[[DIM_1:.*]] = tensor.dim %{{.*}}, %[[C2]] -// CHECK: %[[VAL_2:.*]] = affine.apply #[[$MAP4]]()[%[[DIM_1]], %[[C1]]] -// CHECK: %[[DIM_2:.*]] = tensor.dim %{{.*}}, %[[C2]] -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %{{.*}} {{\[\[}}0, 1], [2, 3], [4]] output_shape [%[[VAL_1]], 1, %[[VAL_2]], 1, %[[DIM_2]]] : tensor into tensor +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2, 3], [4]] // CHECK-SLICES-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1, d2) -> (d0, d2)> // CHECK-SLICES-DAG: #[[$MAP2:.*]] = affine_map<(d0, d1, d2) -> ()> @@ -79,18 +70,13 @@ func.func @drop_one_trip_loops_all_ones(%arg0 : tensor<1x1x1xf32>, %arg1 : f32, } // CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0) -> ()> // CHECK-DAG: #[[$MAP2:.*]] = affine_map<(d0) -> (d0)> -// CHECK-DAG: #[[$MAP3:.*]] = affine_map<()[s0, s1, s2, s3, s4] -> ((((s0 * s1) * s2) * s3) * s4)> // CHECK-LABEL: func @drop_one_trip_loops_all_ones -// CHECK: %[[C2:.*]] = arith.constant 2 : index -// CHECK: %[[C1:.*]] = arith.constant 1 : index // CHECK: tensor.collapse_shape %{{.*}} [] // CHECK: tensor.collapse_shape %{{.*}} {{\[}}[0, 1, 2, 3, 4]] // CHECK: linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP1]], #[[$MAP1]], #[[$MAP2]]] // CHECK-SAME: iterator_types = ["parallel"] -// CHECK: %[[DIM:.*]] = tensor.dim %{{.*}}, %[[C2]] : tensor<1x1x?x1x1xf32> -// CHECK: %[[SZ:.*]] = affine.apply #[[$MAP3]]()[%[[C1]], %[[C1]], %[[DIM]], %[[C1]], %[[C1]]] -// CHECK: %[[EXPAND:.*]] = tensor.expand_shape %{{.*}} {{\[\[}}0, 1, 2, 3, 4]] output_shape [1, 1, %[[SZ]], 1, 1] : tensor into tensor<1x1x?x1x1xf32> +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2, 3, 4]] // ----- @@ -246,8 +232,8 @@ func.func @leading_dim_1_canonicalization(%arg0: tensor<1x5xf32>, %shape: tensor func.func @broadcast_test(%arg0 : tensor<5xf32>, %arg1 : tensor<5xf32>, %shape : tensor<5x5xf32>) -> tensor<5x5xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [1, 5] : tensor<5xf32> into tensor<1x5xf32> - %1 = tensor.expand_shape %arg1 [[0, 1]] output_shape [5, 1] : tensor<5xf32> into tensor<5x1xf32> + %0 = tensor.expand_shape %arg0 [[0, 1]] : tensor<5xf32> into tensor<1x5xf32> + %1 = tensor.expand_shape %arg1 [[0, 1]] : tensor<5xf32> into tensor<5x1xf32> %2 = linalg.generic #trait ins(%0, %1 : tensor<1x5xf32>, tensor<5x1xf32>) outs(%shape : tensor<5x5xf32>) { @@ -345,6 +331,7 @@ func.func @fold_unit_dim_for_empty_tensor(%input: tensor<1x1000xf32>) -> tensor< // CHECK: func @fold_unit_dim_for_empty_tensor + // CHECK: %[[INPUT_RESHAPE:.+]] = tensor.collapse_shape %{{.+}} {{\[}}[0, 1]] : tensor<1x1000xf32> into tensor<1000xf32> // CHECK: %[[INIT:.+]] = tensor.empty() : tensor // CHECK: %[[FILL:.+]] = linalg.fill ins(%cst : f32) outs(%[[INIT]] : tensor) -> tensor @@ -353,7 +340,7 @@ func.func @fold_unit_dim_for_empty_tensor(%input: tensor<1x1000xf32>) -> tensor< // CHECK-SAME: iterator_types = ["reduction"] // CHECK-SAME: ins(%[[INPUT_RESHAPE]] : tensor<1000xf32>) // CHECK-SAME: outs(%[[FILL]] : tensor) -// CHECK: %[[GENERIC_RESHAPE:.+]] = tensor.expand_shape %[[GENERIC]] [] output_shape [1] : tensor into tensor<1xf32> +// CHECK: %[[GENERIC_RESHAPE:.+]] = tensor.expand_shape %[[GENERIC]] [] : tensor into tensor<1xf32> // CHECK: return %[[GENERIC_RESHAPE:.+]] : tensor<1xf32> @@ -377,11 +364,11 @@ func.func @fold_slice( // CHECK: %[[SLICE1:.+]] = tensor.extract_slice %[[ARG0]] // CHECK-SAME: to tensor // CHECK: %[[RESULT1:.+]] = tensor.expand_shape %[[SLICE1]] -// CHECK-SAME: {{\[\[}}0, 1], [2], [3, 4, 5, 6]] output_shape [1, %arg5, %arg6, 1, %arg7, 1, 1] : tensor into tensor<1x?x?x1x?x1x1xf32> +// CHECK-SAME: [0, 1], [2], [3, 4, 5, 6] // CHECK: %[[SLICE2:.+]] = tensor.extract_slice %[[ARG1]] // CHECK-SAME: to tensor // CHECK: %[[RESULT2:.+]] = tensor.expand_shape %[[SLICE2]] -// CHECK-SAME: {{\[\[}}0, 1], [2], [3, 4, 5, 6]] output_shape [1, %arg5, %arg6, 1, %arg7, 1, 1] : tensor into tensor<1x?x?x1x?x1x1xf32> +// CHECK-SAME: [0, 1], [2], [3, 4, 5, 6] // CHECK: return %[[RESULT1]], %[[RESULT2]] // ----- @@ -404,27 +391,20 @@ func.func @unit_dim_for_reduction(%arg0: tensor<1x?x1x?xf32>) -> tensor<1x?xf32> } -> tensor<1x?xf32> return %3 : tensor<1x?xf32> } -// CHECK-DAG: #[[MAP:.+]] = affine_map<(d0, d1) -> (d0, d1)> -// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0)> -// CHECK-DAG: #[[MAP3:.+]] = affine_map<()[s0, s1, s2] -> ((s0 * s1) * s2)> +// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0, d1)> +// CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d0)> // CHECK: func @unit_dim_for_reduction // CHECK-SAME: %[[ARG0:.+]]: tensor<1x?x1x?xf32> -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[CST:.+]] = arith.constant 1.000000e+00 : f32 -// CHECK: %[[C3:.+]] = arith.constant 3 : index -// CHECK: %[[DIM:.+]] = tensor.dim %arg0, %[[C3]] : tensor<1x?x1x?xf32> -// CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] -// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor -// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] -// CHECK: %[[RESULT:.+]] = linalg.generic -// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP2]]] +// CHECK-DAG: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] +// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor +// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] +// CHECK: %[[RESULT:.+]] = linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP3]]] // CHECK-SAME: iterator_types = ["parallel", "reduction"] // CHECK-SAME: ins(%[[RESHAPE]] : tensor) // CHECK-SAME: outs(%[[FILL]] : tensor) -// CHECK: %[[DIM_0:.*]] = tensor.dim %[[ARG0]], %[[C1]] : tensor<1x?x1x?xf32> -// CHECK: %[[VAL_3:.*]] = affine.apply #[[$MAP3]]()[%[[C1]], %[[DIM_0]], %[[C1]]] -// CHECK: %[[EXPANDED:.*]] = tensor.expand_shape %[[GENERIC]] {{\[\[}}0, 1]] output_shape [1, %[[VAL_3]]] : tensor into tensor<1x?xf32> -// CHECK: return %[[EXPANDED]] : tensor<1x?xf32> +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] +// CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -457,7 +437,7 @@ func.func @unit_dim_for_both_reduction(%arg0: tensor<1x?x1x1xf32>) -> tensor<1x1 // CHECK-SAME: iterator_types = ["parallel"] // CHECK-SAME: ins(%[[RESHAPE]], %[[FILL]] : tensor, tensor<1xf32>) // CHECK-SAME: outs(%[[INIT2]] : tensor<1xf32>) -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] output_shape [1, 1] +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] // CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -480,28 +460,20 @@ func.func @unit_dim_for_reduction_inner(%arg0: tensor) -> tensor tensor return %3 : tensor } -// CHECK-DAG: #[[MAP:.+]] = affine_map<(d0, d1) -> (d0, d1)> -// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0)> -// CHECK-DAG: #[[MAP3:.+]] = affine_map<()[s0, s1] -> (s0 * s1)> +// CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d0, d1)> +// CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d0)> // CHECK: func @unit_dim_for_reduction_inner // CHECK-SAME: %[[ARG0:.+]]: tensor -// CHECK: %[[C1:.*]] = arith.constant 1 : index -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[CST:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK: %[[C2:.*]] = arith.constant 2 : index -// CHECK: %[[DIM:.*]] = tensor.dim %arg0, %[[C2]] : tensor -// CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]] -// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor -// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] -// CHECK: %[[RESULT:.+]] = linalg.generic -// CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP2]]] +// CHECK-DAG: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]] +// CHECK: %[[INIT:.+]] = tensor.empty(%{{.+}}) : tensor +// CHECK: %[[FILL:.+]] = linalg.fill ins(%{{.+}}{{.*}}outs(%[[INIT]] +// CHECK: %[[RESULT:.+]] = linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP3]]] // CHECK-SAME: iterator_types = ["parallel", "reduction"] // CHECK-SAME: ins(%[[RESHAPE]] : tensor) // CHECK-SAME: outs(%[[FILL]] : tensor) -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[VAL_3:.+]] = affine.apply #[[$MAP3]]()[%[[DIM_0]], %[[C1]]] -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] output_shape [%[[VAL_3]], 1] : tensor into tensor -// CHECK: return %[[RESULT_RESHAPE]] +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[RESULT]] {{\[}}[0, 1]] +// CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -512,7 +484,7 @@ func.func @slice_unit_dims(%arg0: tensor<1x3xf32>) -> tensor<1x1xf32> { // CHECK-LABEL: func @slice_unit_dims // CHECK: %[[SLICE:.+]] = tensor.extract_slice // CHECK-SAME: tensor<1x3xf32> to tensor -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] [] output_shape [1, 1] +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] [] // CHECK: return %[[RESULT]] // ----- @@ -524,7 +496,7 @@ func.func @rank_reduced_extract_slice(%arg0: tensor<1x1x3x1x3xf32>) -> tensor<1x // CHECK-LABEL: func @rank_reduced_extract_slice // CHECK: %[[SLICE:.+]] = tensor.extract_slice // CHECK-SAME: tensor<1x1x3x1x3xf32> to tensor<3x3xf32> -// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] {{\[}}[0, 1], [2]] output_shape [1, 3, 3] +// CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[SLICE]] {{\[}}[0, 1], [2]] // CHECK: return %[[RESULT]] // ----- @@ -737,8 +709,8 @@ func.func @leading_dim_1_canonicalization(%arg0: memref<1x5xf32>, %shape: memref func.func @broadcast_test(%arg0 : memref<5xf32>, %arg1 : memref<5xf32>, %shape : memref<5x5xf32>) -> memref<5x5xf32> { - %0 = memref.expand_shape %arg0 [[0, 1]] output_shape [1, 5] : memref<5xf32> into memref<1x5xf32> - %1 = memref.expand_shape %arg1 [[0, 1]] output_shape [5, 1] : memref<5xf32> into memref<5x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1]] : memref<5xf32> into memref<1x5xf32> + %1 = memref.expand_shape %arg1 [[0, 1]] : memref<5xf32> into memref<5x1xf32> linalg.generic #trait ins(%0, %1 : memref<1x5xf32>, memref<5x1xf32>) outs(%shape : memref<5x5xf32>) { @@ -994,7 +966,7 @@ func.func @drop_unit_pad_dims(%arg0: tensor<1x1x3x1x1xf32>) -> tensor<1x2x3x1x3x // CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0, 0] high[0, 0, 2] // CHECK: } : tensor<1x3x1xf32> to tensor<2x3x3xf32> // CHECK: tensor.expand_shape %[[PADDED]] -// CHECK-SAME: {{\[}}[0, 1], [2, 3], [4]{{\]}} output_shape [1, 2, 3, 1, 3] : tensor<2x3x3xf32> into tensor<1x2x3x1x3xf32> +// CHECK-SAME: {{\[}}[0, 1], [2, 3], [4]{{\]}} : tensor<2x3x3xf32> into tensor<1x2x3x1x3xf32> // CHECK-SLICES-LABEL: func @drop_unit_pad_dims // CHECK-SLICES: %[[EXTRACT:.+]] = tensor.extract_slice @@ -1017,19 +989,13 @@ func.func @drop_unit_pad_dynamic_dims(%arg0: tensor<1x?xf32>) -> tensor<1x?xf32> return %0 : tensor<1x?xf32> } -// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 * s1)> -// CHECK-DAG: #[[$MAP1:.+]] = affine_map<()[s0] -> (s0 + 11)> // CHECK-LABEL: func @drop_unit_pad_dynamic_dims -// CHECK: %[[C1:.*]] = arith.constant 1 : index -// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape // CHECK-SAME: {{\[}}[0, 1]{{\]}} : tensor<1x?xf32> into tensor // CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[5] high[6] // CHECK: } : tensor to tensor -// CHECK: %[[DIM:.+]] = tensor.dim %{{.*}}, %[[C1]] : tensor<1x?xf32> -// CHECK: %[[VAL_0:.+]] = affine.apply #[[$MAP]]()[%[[C1]], %[[DIM]]] -// CHECK: %[[VAL_1:.+]] = affine.apply #[[$MAP1]]()[%[[VAL_0]]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[PADDED]] {{\[\[}}0, 1]] output_shape [1, %[[VAL_1]]] : tensor into tensor<1x?xf32> +// CHECK: tensor.expand_shape %[[PADDED]] +// CHECK-SAME: {{\[}}[0, 1]{{\]}} : tensor into tensor<1x?xf32> // CHECK-SLICES: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 + 11)> @@ -1086,4 +1052,4 @@ func.func @drop_known_unit_constant_low_high(%arg0: tensor<1x383x128xf32>) -> te // CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0] high[0, 0] // CHECK: } : tensor<383x128xf32> to tensor<384x128xf32> // CHECK: tensor.expand_shape %[[PADDED]] -// CHECK-SAME: {{\[}}[0, 1], [2]] output_shape [1, 384, 128] : tensor<384x128xf32> into tensor<1x384x128xf32> +// CHECK-SAME: {{\[}}[0, 1], [2]] : tensor<384x128xf32> into tensor<1x384x128xf32> diff --git a/mlir/test/Dialect/Linalg/flatten-elementwise.mlir b/mlir/test/Dialect/Linalg/flatten-elementwise.mlir index 9fe50a521d2d..5a27fe76b134 100644 --- a/mlir/test/Dialect/Linalg/flatten-elementwise.mlir +++ b/mlir/test/Dialect/Linalg/flatten-elementwise.mlir @@ -26,7 +26,7 @@ module attributes {transform.with_named_sequence} { // CHECK-SAME: %[[ARG1:.*]]: tensor<32x7xf32> // CHECK-NEXT: %[[FLATTENED:.*]] = tensor.collapse_shape %[[ARG1]] {{\[}}[0, 1]] // CHECK-NEXT: %[[FLATTENED_RESULT:.*]] = linalg.fill ins(%[[ARG0]] : f32) outs(%[[FLATTENED]] : tensor<224xf32>) -// CHECK-NEXT: %[[RESULT:.*]] = tensor.expand_shape %[[FLATTENED_RESULT]] {{\[}}[0, 1]] output_shape [32, 7] : tensor<224xf32> into tensor<32x7xf32> +// CHECK-NEXT: %[[RESULT:.*]] = tensor.expand_shape %[[FLATTENED_RESULT]] {{\[}}[0, 1]] func.func @fill_tensor(%cst: f32, %arg: tensor<32x7xf32>) -> tensor<32x7xf32> { %0 = linalg.fill ins(%cst: f32) outs(%arg: tensor<32x7xf32>) -> tensor<32x7xf32> return %0 : tensor<32x7xf32> diff --git a/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir b/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir index 0d40df534a3b..50d308b6a9fe 100644 --- a/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir +++ b/mlir/test/Dialect/Linalg/fuse-with-reshape-by-collapsing.mlir @@ -9,7 +9,8 @@ #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing(%arg0 : tensor<2x12x5x336x9xi32>, %arg1 : tensor<2x3x4xi32>, %arg2 : tensor<5x6x7x8xi32>) -> tensor<2x3x4x5x6x7x8x9xi32> { - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [2, 3, 4, 5, 6, 7, 8, 9] : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] + : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> %init = tensor.empty() : tensor<2x3x4x5x6x7x8x9xi32> %generic = linalg.generic { indexing_maps = [#map0, #map1, #map2, #map3], @@ -39,7 +40,7 @@ func.func @fuse_by_collapsing(%arg0 : tensor<2x12x5x336x9xi32>, // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel", "parallel", "parallel"] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1_RESHAPE]], %[[ARG2_RESHAPE]] : // CHECK-SAME: outs(%[[INIT_RESHAPE]] : -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2], [3], [4, 5, 6], [7]{{\]}} output_shape [2, 3, 4, 5, 6, 7, 8, 9] +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2], [3], [4, 5, 6], [7]{{\]}} // CHECK: return %[[RESULT_RESHAPE]] // CONTROL: func @fuse_by_collapsing( @@ -59,7 +60,8 @@ func.func @fuse_by_collapsing(%arg0 : tensor<2x12x5x336x9xi32>, #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing_indexing_op(%arg0 : tensor<2x12x5x336x9xi32>, %arg1 : tensor<2x3x4xi32>, %arg2 : tensor<5x6x7x8xi32>) -> tensor<2x3x4x5x6x7x8x9xi32> { - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [2, 3, 4, 5, 6, 7, 8, 9] : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] + : tensor<2x12x5x336x9xi32> into tensor<2x3x4x5x6x7x8x9xi32> %init = tensor.empty() : tensor<2x3x4x5x6x7x8x9xi32> %generic = linalg.generic { indexing_maps = [#map0, #map1, #map2, #map3], @@ -120,7 +122,8 @@ func.func @fuse_by_collapsing_indexing_op(%arg0 : tensor<2x12x5x336x9xi32>, #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing_change_reshape_order(%arg0 : tensor<9x56x2x60x6xi32>, %arg1 : tensor<7x8x2xi32>, %arg2 : tensor<6x3x4x5xi32>) -> tensor<2x3x4x5x6x7x8x9xi32> { - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [9, 7, 8, 2, 3, 4, 5, 6] : tensor<9x56x2x60x6xi32> into tensor<9x7x8x2x3x4x5x6xi32> + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] + : tensor<9x56x2x60x6xi32> into tensor<9x7x8x2x3x4x5x6xi32> %init = tensor.empty() : tensor<2x3x4x5x6x7x8x9xi32> %generic = linalg.generic { indexing_maps = [#map0, #map1, #map2, #map3], @@ -151,7 +154,7 @@ func.func @fuse_by_collapsing_change_reshape_order(%arg0 : tensor<9x56x2x60x6xi3 // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel", "parallel", "parallel"] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1_RESHAPE]], %[[ARG2_RESHAPE]] : // CHECK-SAME: outs(%[[INIT_RESHAPE]] : -// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2, 3], [4], [5, 6], [7]{{\]}} output_shape [2, 3, 4, 5, 6, 7, 8, 9] +// CHECK: %[[RESULT_RESHAPE:.+]] = tensor.expand_shape %[[COLLAPSED_OP]] {{\[}}[0], [1, 2, 3], [4], [5, 6], [7]{{\]}} // CHECK: return %[[RESULT_RESHAPE]] // ----- @@ -162,11 +165,11 @@ func.func @fuse_by_collapsing_change_reshape_order(%arg0 : tensor<9x56x2x60x6xi3 #map2 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d4, d1, d2, d3)> #map3 = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0, d1, d2, d3, d4, d5, d6, d7)> func.func @fuse_by_collapsing_dynamic(%arg0 : tensor, - %arg1 : tensor, %arg2 : tensor, %sz0: index, %sz1: index, %sz2: index, %sz3: index, %sz4: index) -> tensor { + %arg1 : tensor, %arg2 : tensor) -> tensor { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index - %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] output_shape [%sz0, 7, %sz1, %sz2, 3, %sz3, 5, %sz4] + %expand = tensor.expand_shape %arg0 [[0], [1, 2], [3], [4, 5, 6], [7]] : tensor into tensor %d0 = tensor.dim %arg1, %c2 : tensor %d2 = tensor.dim %arg2, %c2 : tensor @@ -200,8 +203,8 @@ func.func @fuse_by_collapsing_dynamic(%arg0 : tensor, } -> tensor return %generic : tensor } -// CHECK: func @fuse_by_collapsing_dynamic -// CHECK-SAME: (%[[ARG0:.+]]: tensor, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index, %[[SZ2:.+]]: index, %[[SZ3:.+]]: index, %[[SZ4:.+]]: index) +// CHECK: func @fuse_by_collapsing_dynamic( +// CHECK-SAME: %[[ARG0:.+]]: tensor // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index // CHECK-DAG: %[[C5:.+]] = arith.constant 5 : index // CHECK: %[[EXPAND:.+]] = tensor.expand_shape %[[ARG0]] @@ -221,8 +224,8 @@ func.func @fuse_by_collapsing_dynamic(%arg0 : tensor, #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d3)> -func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>, %sz0: index) -> tensor<2x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 6, %sz0, 5] : tensor<2x?x5xf32> into tensor<2x6x?x5xf32> +func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>) -> tensor<2x5xf32> { + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x?x5xf32> into tensor<2x6x?x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1], iterator_types = ["parallel", "reduction", "reduction", "parallel"]} @@ -237,8 +240,7 @@ func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>, % // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2) -> (d0, d2)> // CHECK: func @fuse_reductions( // CHECK-SAME: %[[ARG0:.+]]: tensor<2x?x5xf32> -// CHECK-SAME: %[[ARG1:.+]]: tensor<2x5xf32> -// CHECK-SAME: %[[SZ0:.+]]: index) -> tensor<2x5xf32> +// CHECK-SAME: %[[ARG1:.+]]: tensor<2x5xf32>) -> tensor<2x5xf32> // CHECK: %[[GENERIC:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]]] // CHECK-SAME: iterator_types = ["parallel", "reduction", "parallel"] @@ -251,7 +253,7 @@ func.func @fuse_reductions(%arg0 : tensor<2x?x5xf32>, %arg1 : tensor<2x5xf32>, % #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1)> func.func @no_fuse_unpreserved_folding(%arg0 : tensor<2x12x5xf32>, %arg1 : tensor<2x3xf32>) -> tensor<2x3x4x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 3, 4, 5] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> %init = tensor.empty(): tensor<2x3x4x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1, #map0], @@ -278,7 +280,7 @@ func.func @no_fuse_unpreserved_folding(%arg0 : tensor<2x12x5xf32>, %arg1 : tenso #map1 = affine_map<(d0, d1, d2, d3) -> (d0)> #map2 = affine_map<(d0, d1, d2, d3) -> (d0, d2, d1, d3)> func.func @no_fuse_unpreserved_folding_transpose(%arg0 : tensor<2x12x5xf32>, %arg1 : tensor<2xf32>) -> tensor<2x4x3x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 3, 4, 5] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> %init = tensor.empty() : tensor<2x4x3x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1, #map2], @@ -305,7 +307,7 @@ func.func @no_fuse_unpreserved_folding_transpose(%arg0 : tensor<2x12x5xf32>, %ar #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1)> #map2 = affine_map<(d0, d1, d2, d3) -> (d0, d3)> func.func @no_fuse_mismatched_iterator_types(%arg0 : tensor<2x12x5xf32>, %arg1 : tensor<2x3xf32>) -> tensor<2x5xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] output_shape [2, 3, 4, 5] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> + %0 = tensor.expand_shape %arg0 [[0], [1, 2], [3]] : tensor<2x12x5xf32> into tensor<2x3x4x5xf32> %init = tensor.empty() : tensor<2x5xf32> %1 = linalg.generic { indexing_maps = [#map0, #map1, #map2], @@ -333,8 +335,8 @@ func.func @no_fuse_mismatched_iterator_types(%arg0 : tensor<2x12x5xf32>, %arg1 : #map1 = affine_map<(d0, d1, d2, d3) -> (d2, d3)> #map2 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> func.func @control_fusion(%arg0 : tensor<6xf32>, %arg1 : tensor<20xf32>) -> tensor<2x3x4x5xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [2, 3] : tensor<6xf32> into tensor<2x3xf32> - %1 = tensor.expand_shape %arg1 [[0, 1]] output_shape [4, 5] : tensor<20xf32> into tensor<4x5xf32> + %0 = tensor.expand_shape %arg0 [[0, 1]] : tensor<6xf32> into tensor<2x3xf32> + %1 = tensor.expand_shape %arg1 [[0, 1]] : tensor<20xf32> into tensor<4x5xf32> %init = tensor.empty() : tensor<2x3x4x5xf32> %2 = linalg.generic { indexing_maps = [#map0, #map1, #map2], @@ -357,8 +359,8 @@ func.func @control_fusion(%arg0 : tensor<6xf32>, %arg1 : tensor<20xf32>) -> tens // CHECK-SAME: iterator_types = ["parallel", "parallel"] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1]] : // CHECK-SAME: outs(%{{.+}}: tensor<6x20xf32>) -// CHECK: %[[RESHAPE1:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1, 2]{{\]}} output_shape [6, 4, 5] -// CHECK: %[[RESHAPE2:.+]] = tensor.expand_shape %[[RESHAPE1]] {{\[}}[0, 1], [2], [3]{{\]}} output_shape [2, 3, 4, 5] +// CHECK: %[[RESHAPE1:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1, 2]{{\]}} +// CHECK: %[[RESHAPE2:.+]] = tensor.expand_shape %[[RESHAPE1]] {{\[}}[0, 1], [2], [3]{{\]}} // CHECK: return %[[RESHAPE2]] // CONTROL-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d1)> @@ -373,14 +375,14 @@ func.func @control_fusion(%arg0 : tensor<6xf32>, %arg1 : tensor<20xf32>) -> tens // CONTROL: %[[GENERIC:.+]] = linalg.generic // CONTROL-SAME: ins(%[[EXPAND]], %[[ARG1]] : // CONTROL-SAME: outs(%[[INIT_RESHAPE]] : -// CONTROL: %[[RESULT:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1], [2, 3]{{\]}} output_shape [2, 3, 4, 5] +// CONTROL: %[[RESULT:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1], [2, 3]{{\]}} // ----- // Corner case that isnt handled currently. #map = affine_map<(d0) -> (d0)> func.func @zero_D_test(%arg0: tensor) -> tensor<1xf32> { - %0 = tensor.expand_shape %arg0 [] output_shape [1] : tensor into tensor<1xf32> + %0 = tensor.expand_shape %arg0 [] : tensor into tensor<1xf32> %init = tensor.empty() : tensor<1xf32> %1 = linalg.generic { indexing_maps = [#map, #map], @@ -402,8 +404,8 @@ func.func @zero_D_test(%arg0: tensor) -> tensor<1xf32> { #map0 = affine_map<(d0, d1, d2, d3) -> (d1, d0, d2, d3)> #map1 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)> -func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4x?x?x8xf32>, %sz0: index, %sz1: index) -> tensor<4x?x?x8xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [%sz0, 4, %sz1, 8] : tensor into tensor +func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4x?x?x8xf32>) -> tensor<4x?x?x8xf32> { + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] : tensor into tensor %1 = linalg.generic { indexing_maps = [#map0, #map1, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} @@ -417,12 +419,10 @@ func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4 } // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2) -> (d1, d0, d2)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)> -// CHECK: func @fuse_only_one_reassociation -// CHECK-SAME: (%[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor<4x?x?x8xf32>, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index) -// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index -// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index -// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index -// CHECK-DAG: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} output_shape [%[[SZ0]], 4, %[[SZ1]], 8] +// CHECK: func @fuse_only_one_reassociation( +// CHECK-SAME: %[[ARG0:.+]]: tensor +// CHECK-SAME: %[[ARG1:.+]]: tensor<4x?x?x8xf32> +// CHECK-DAG: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} // CHECK-DAG: %[[COLLAPSE_ARG0:.+]] = tensor.collapse_shape %[[EXPAND_ARG0]] {{\[}}[0], [1], [2, 3]{{\]}} // CHECK-DAG: %[[COLLAPSE_ARG1_0:.+]] = tensor.collapse_shape %[[ARG1]] {{\[}}[0], [1], [2, 3]{{\]}} // CHECK-DAG: %[[COLLAPSE_ARG1_1:.+]] = tensor.collapse_shape %[[ARG1]] {{\[}}[0], [1], [2, 3]{{\]}} @@ -431,20 +431,17 @@ func.func @fuse_only_one_reassociation(%arg0 : tensor, %arg1 : tensor<4 // CHECK-SAME: iterator_types = ["parallel", "parallel", "parallel"] // CHECK-SAME: ins(%[[COLLAPSE_ARG0]], %[[COLLAPSE_ARG1_0]] : // CHECK-SAME: outs(%[[COLLAPSE_ARG1_1]] : -// CHECK: %[[DIM:.+]] = tensor.dim %[[GENERIC]], %[[C1]] : tensor<4x?x?xf32> -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[GENERIC]], %[[C2]] : tensor<4x?x?xf32> -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C8]] : index -// CHECK: %[[EXPANDED_3:.+]] = tensor.expand_shape %[[GENERIC]] {{\[\[}}0], [1], [2, 3]] output_shape [4, %[[DIM]], %[[VAL_1]], 8] : tensor<4x?x?xf32> into tensor<4x?x?x8xf32> -// CHECK: return %[[EXPANDED_3]] +// CHECK: %[[EXPAND_GENERIC:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0], [1], [2, 3]{{\]}} +// CHECK: return %[[EXPAND_GENERIC]] // ----- #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d2, d3, d1)> #map1 = affine_map<(d0, d1, d2, d3) -> (d3, d1, d0, d2)> -func.func @fold_non_consecutive_dims(%arg0 : tensor, %sz0: index, %sz1: index) -> tensor { +func.func @fold_non_consecutive_dims(%arg0 : tensor) -> tensor { %c0 = arith.constant 0 : index %c2 = arith.constant 2 : index - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [%sz0, 4, %sz1, 8] : tensor into tensor + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] : tensor into tensor %d0 = tensor.dim %0, %c0 : tensor %d1 = tensor.dim %0, %c2 : tensor %init = tensor.empty(%d1, %d0) : tensor @@ -468,16 +465,10 @@ func.func @fold_non_consecutive_dims(%arg0 : tensor, %sz0: index, %sz1: // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)> // CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d1, d0)> // CHECK: func @fold_non_consecutive_dims( -// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index) -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C4:.+]] = arith.constant 4 : index -// CHECK: %[[C8:.+]] = arith.constant 8 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[C2:.+]] = arith.constant 2 : index -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[SZ0]], 4, %[[SZ1]], 8] : tensor into tensor -// CHECK: %[[DIM:.+]] = tensor.dim %[[EXPANDED]], %[[C0]] -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[EXPANDED]], %[[C2]] -// CHECK: %[[INIT:.+]] = tensor.empty(%[[DIM_0]], %[[DIM]]) +// CHECK-SAME: %[[ARG0:.+]]: tensor) +// CHECK-DAG: %[[C4:.+]] = arith.constant 4 : index +// CHECK-DAG: %[[C8:.+]] = arith.constant 8 : index +// CHECK: %[[INIT:.+]] = tensor.empty // CHECK: %[[COLLAPSE_INIT:.+]] = tensor.collapse_shape %[[INIT]] {{\[}}[0, 1], [2, 3]{{\]}} // CHECK: %[[GENERIC:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]]] @@ -496,12 +487,8 @@ func.func @fold_non_consecutive_dims(%arg0 : tensor, %sz0: index, %sz1: // CHECK-DAG: %[[T6:.+]] = arith.addi %[[T5]], %[[T3]] // CHECK-DAG: %[[T7:.+]] = arith.index_cast %[[T6]] // CHECK: linalg.yield %[[T7]] -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[GENERIC]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[GENERIC]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_1]], %[[C8]] : index -// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_2]], %[[C4]] : index -// CHECK: %[[EXPANDED_3:.+]] = tensor.expand_shape %[[GENERIC]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_2]], 8, %[[VAL_3]], 4] : tensor into tensor -// CHECK: return %[[EXPANDED_3]] +// CHECK: %[[EXPAND_GENERIC:.+]] = tensor.expand_shape %[[GENERIC]] {{\[}}[0, 1], [2, 3]{{\]}} +// CHECK: return %[[EXPAND_GENERIC]] // ----- @@ -509,10 +496,10 @@ func.func @fold_non_consecutive_dims(%arg0 : tensor, %sz0: index, %sz1: // So no change in the code. #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d2, d3, d1)> #map1 = affine_map<(d0, d1, d2, d3) -> ()> -func.func @no_fold_non_consecutive_reduction_dims(%arg0 : tensor, %sz0: index, %sz1: index) -> tensor { +func.func @no_fold_non_consecutive_reduction_dims(%arg0 : tensor) -> tensor { %c0 = arith.constant 0 : index %c2 = arith.constant 2 : index - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [%sz0, 4, %sz1, 8] : tensor into tensor + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] : tensor into tensor %init = tensor.empty() : tensor %1 = linalg.generic { indexing_maps = [#map0, #map1], @@ -532,8 +519,8 @@ func.func @no_fold_non_consecutive_reduction_dims(%arg0 : tensor, %sz0: return %1 : tensor } // CHECK: func @no_fold_non_consecutive_reduction_dims( -// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[SZ0:.+]]: index, %[[SZ1:.+]]: index) -// CHECK: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} output_shape [%[[SZ0]], 4, %[[SZ1]], 8] +// CHECK-SAME: %[[ARG0:.+]]: tensor) +// CHECK: %[[EXPAND_ARG0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2, 3]{{\]}} // CHECK: %[[GENERIC:.+]] = linalg.generic // CHECK-SAME: ins(%[[EXPAND_ARG0]] : // CHECK: return %[[GENERIC]] diff --git a/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir b/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir index 751ece37bc09..f1c729ef963b 100644 --- a/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir +++ b/mlir/test/Dialect/Linalg/fusion-push-reshape.mlir @@ -4,19 +4,15 @@ // CHECK-DAG: #[[$MAP3:.*]] = affine_map<(d0, d1) -> (d1)> // CHECK-LABEL: func @reshape -// CHECK-SAME: (%[[A:.*]]: tensor, %[[B:.*]]: tensor<16xf32>, %[[INIT:.*]]: tensor, %[[SZ0:.*]]: index) -// CHECK: %[[C112:.*]] = arith.constant 112 : index -// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK-SAME: (%[[A:.*]]: tensor, %[[B:.*]]: tensor<16xf32>, %[[INIT:.*]]: tensor) // CHECK: %[[RI:.*]] = tensor.collapse_shape %[[INIT]] {{\[}}[0, 1], [2]] : tensor into tensor // CHECK: %[[R:.*]] = linalg.generic {indexing_maps = [#[[$MAP2]], #[[$MAP3]], #[[$MAP2]]], // CHECK-SAME: iterator_types = ["parallel", "parallel"]} // CHECK-SAME: ins(%[[A]], %[[B]] : tensor, tensor<16xf32>) outs(%[[RI]] : tensor) -// CHECK: %[[DIM:.*]] = tensor.dim %[[R]], %[[C0]] : tensor -// CHECK: %[[VAL_1:.*]] = arith.divui %[[DIM]], %[[C112]] : index -// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[\[}}0, 1], [2]] output_shape [%[[VAL_1]], 112, 16] : tensor into tensor +// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[}}[0, 1], [2]] : tensor into tensor // CHECK: return %[[RR]] : tensor -func.func @reshape(%A: tensor, %B: tensor<16xf32>, %init: tensor, %sz0: index) -> tensor { - %0 = tensor.expand_shape %A [[0, 1], [2]] output_shape [%sz0, 112, 16] +func.func @reshape(%A: tensor, %B: tensor<16xf32>, %init: tensor) -> tensor { + %0 = tensor.expand_shape %A [[0, 1], [2]] : tensor into tensor %2 = linalg.generic {indexing_maps = [ affine_map<(d0, d1, d2) -> (d0, d1, d2)>, affine_map<(d0, d1, d2) -> (d2)>, @@ -43,13 +39,13 @@ func.func @reshape(%A: tensor, %B: tensor<16xf32>, %init: tensor, tensor<12544x16xf32>, tensor<16xf32>) outs(%[[RI]] : tensor<12544x16xf32>) -// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[}}[0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> +// CHECK: %[[RR:.*]] = tensor.expand_shape %[[R]] {{\[}}[0, 1], [2]] : tensor<12544x16xf32> into tensor<112x112x16xf32> // CHECK: return %[[RR]] : tensor<112x112x16xf32> func.func @reshape_multiple(%A: tensor<12544x16xf32>, %B: tensor<12544x16xf32>, %C: tensor<16xf32>) -> tensor<112x112x16xf32> { - %0 = tensor.expand_shape %A [[0, 1], [2]] output_shape [112, 112, 16] + %0 = tensor.expand_shape %A [[0, 1], [2]] : tensor<12544x16xf32> into tensor<112x112x16xf32> - %1 = tensor.expand_shape %B [[0, 1], [2]] output_shape [112, 112, 16] + %1 = tensor.expand_shape %B [[0, 1], [2]] : tensor<12544x16xf32> into tensor<112x112x16xf32> %2 = tensor.empty() : tensor<112x112x16xf32> %3 = linalg.generic {indexing_maps = [ @@ -73,11 +69,11 @@ func.func @reshape_multiple(%A: tensor<12544x16xf32>, %B: tensor<12544x16xf32>, // Negative test, since the second source is broadcasted from d1 we cannot merge // d0 and d1 dimensions // CHECK-LABEL: func @reshape_negative -// CHECK: tensor.expand_shape {{.*}} {{\[\[}}0, 1], [2]] output_shape [112, 112, 16] : tensor<12544x16xf32> into tensor<112x112x16xf32> +// CHECK: tensor.expand_shape {{.*}} : tensor<12544x16xf32> into tensor<112x112x16xf32> // CHECK: linalg.generic // CHECK: } -> tensor<112x112x16xf32> func.func @reshape_negative(%A: tensor<12544x16xf32>, %B: tensor<112xf32>) -> tensor<112x112x16xf32> { - %20 = tensor.expand_shape %A [[0, 1], [2]] output_shape [112, 112, 16] + %20 = tensor.expand_shape %A [[0, 1], [2]] : tensor<12544x16xf32> into tensor<112x112x16xf32> %21 = tensor.empty() : tensor<112x112x16xf32> %22 = linalg.generic {indexing_maps = [ @@ -100,7 +96,7 @@ func.func @type_correctness(%arg0 : tensor<6x5xi32>, %arg1 : tensor<5xf32>, %cst_6 = arith.constant 1.000000e+00 : f32 %cst_7 = arith.constant 7.000000e+00 : f32 %cst_8 = arith.constant 1.1920929E-7 : f32 - %25 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [2, 3, 5] + %25 = tensor.expand_shape %arg0 [[0, 1], [2]] : tensor<6x5xi32> into tensor<2x3x5xi32> %26 = tensor.empty() : tensor<2x3x5xf32> %28 = linalg.generic { diff --git a/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir b/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir index 0f0337a3604e..ab948988b7b6 100644 --- a/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir +++ b/mlir/test/Dialect/Linalg/reshape_control_fusion.mlir @@ -48,7 +48,7 @@ func.func @control_consumer_reshape_fusion(%arg0 : tensor<1x?x?xf32>, %arg1 : te ^bb0(%arg2: f32): linalg.yield %cst : f32 } -> tensor - %0 = tensor.expand_shape %fill [[0, 1], [2]] output_shape [1, %d0, %d1] : tensor into tensor<1x?x?xf32> + %0 = tensor.expand_shape %fill [[0, 1], [2]] : tensor into tensor<1x?x?xf32> %1 = linalg.batch_matmul ins(%arg0, %arg1 : tensor<1x?x?xf32>, tensor<1x?x?xf32>) outs(%0 : tensor<1x?x?xf32>) -> tensor<1x?x?xf32> return %1 : tensor<1x?x?xf32> diff --git a/mlir/test/Dialect/Linalg/reshape_fusion.mlir b/mlir/test/Dialect/Linalg/reshape_fusion.mlir index f42666f81bba..342c067b5c4b 100644 --- a/mlir/test/Dialect/Linalg/reshape_fusion.mlir +++ b/mlir/test/Dialect/Linalg/reshape_fusion.mlir @@ -30,20 +30,10 @@ func.func @generic_op_reshape_producer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: f32 -// CHECK: %[[C4:.+]] = arith.constant 4 : index -// CHECK: %[[C2:.+]] = arith.constant 2 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C2]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM_1]], %[[C4]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1], [2, 3]] output_shape [%[[DIM]], %[[DIM_0]], %[[VAL_0]], 4] : tensor into tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_3:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG1]], %[[C2]] : tensor -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_4]], %[[C4]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1], [2, 3]] output_shape [%[[DIM_2]], %[[DIM_3]], %[[VAL_1]], 4] : tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0], [1], [2, 3] +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0], [1], [2, 3] // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP5]], #[[MAP6]], #[[MAP7]], #[[MAP6]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -60,9 +50,7 @@ func.func @generic_op_reshape_producer_fusion(%arg0 : tensor, #map1 = affine_map<(d0, d1) -> ()> func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, %arg1 : tensor, - %arg2 : f32, - %sz0: index, - %sz1: index) -> + %arg2 : f32) -> tensor { %0 = linalg.generic { @@ -75,7 +63,7 @@ func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, %2 = arith.addf %1, %arg5 : f32 linalg.yield %2 : f32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, 4, %sz1, 5] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : tensor into tensor return %1 : tensor } @@ -87,22 +75,14 @@ func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: f32 -// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index -// CHECK: %[[C20:.+]] = arith.constant 20 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM_0]], %[[C20]] : index -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM]], 4, %[[VAL_0]], 5] : tensor into tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C20]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_1]], 4, %[[VAL_1]], 5] : tensor into tensor -// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_5]], %[[C20]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_4]], 4, %[[VAL_2]], 5] : tensor into tensor +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP2]], #[[MAP3]], #[[MAP2]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -114,7 +94,7 @@ func.func @generic_op_reshape_consumer_fusion(%arg0 : tensor, // ----- func.func @reshape_as_consumer_permutation - (%a : tensor, %b : tensor, %sz0: index, %sz1: index, %sz2: index) + (%a : tensor, %b : tensor) -> tensor { %c = linalg.generic { indexing_maps = [affine_map<(d0, d1, d2) -> (d1, d0, d2)>, @@ -127,7 +107,8 @@ func.func @reshape_as_consumer_permutation %1 = arith.addf %arg0, %arg1 : f32 linalg.yield %1 : f32 } -> tensor - %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] output_shape [%sz0, 2, %sz1, 3, 4, %sz2] : tensor into tensor + %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] + : tensor into tensor return %d : tensor } // CHECK-DAG: #[[MAP8:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d2, d3, d4, d0, d1, d5)> @@ -136,27 +117,15 @@ func.func @reshape_as_consumer_permutation // CHECK: func @reshape_as_consumer_permutation // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor -// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index, %[[SZ2:.+]]: index -// CHECK: %[[C12:.+]] = arith.constant 12 : index -// CHECK: %[[C2:.+]] = arith.constant 2 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C12]] : index -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C2]] : index -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3, 4], [5]] output_shape [3, 4, %[[VAL_0]], %[[VAL_1]], 2, %[[DIM_1]]] : tensor into tensor<3x4x?x?x2x?xf32> -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_3:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_2]], %[[C12]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [3, 4, %[[VAL_2]], %[[DIM_3]]] : tensor into tensor<3x4x?x?xf32> -// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_6:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[DIM_7:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor -// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_5]], %[[C2]] : index -// CHECK: %[[VAL_4:.+]] = arith.divui %[[DIM_7]], %[[C12]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2], [3, 4, 5]] output_shape [%[[VAL_3]], 2, %[[DIM_6]], 3, 4, %[[VAL_4]]] : tensor into tensor +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0, 1, 2], [3, 4], [5] +// CHECK-SAME: tensor into tensor<3x4x?x?x2x?xf32> +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0, 1, 2], [3] +// CHECK-SAME: tensor into tensor<3x4x?x?xf32> +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0, 1], [2], [3, 4, 5]] +// CHECK-SAME: tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP8]], #[[MAP9]], #[[MAP10]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel", "parallel", "parallel"] @@ -183,7 +152,7 @@ func.func @generic_op_reshape_consumer_static(%arg0: tensor<264x4xf32>) %2 = arith.mulf %arg1, %arg2 : f32 linalg.yield %2 : f32 } -> tensor<264x4xf32> - %2 = tensor.expand_shape %1 [[0, 1], [2]] output_shape [8, 33, 4] : + %2 = tensor.expand_shape %1 [[0, 1], [2]] : tensor<264x4xf32> into tensor<8x33x4xf32> return %2 : tensor<8x33x4xf32> } @@ -194,8 +163,12 @@ func.func @generic_op_reshape_consumer_static(%arg0: tensor<264x4xf32>) // CHECK-DAG: %[[CST:.+]] = arith.constant // CHECK-SAME: : tensor<8x33x4xf32> // CHECK-DAG: %[[INIT:.+]] = tensor.empty() -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2]] output_shape [8, 33, 4] : tensor<264x4xf32> into tensor<8x33x4xf32> -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1], [2]] output_shape [8, 33, 4] : tensor<264x4xf32> into tensor<8x33x4xf32> +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0, 1], [2] +// CHECK-SAME: tensor<264x4xf32> into tensor<8x33x4xf32> +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[INIT]] +// CHECK-SAME: [0, 1], [2] +// CHECK-SAME: : tensor<264x4xf32> into tensor<8x33x4xf32> // CHECK: %[[T2:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP2]], #[[MAP2]], #[[MAP2]]] // CHECK-SAME: ["parallel", "parallel", "parallel"] @@ -259,8 +232,7 @@ func.func @indexed_consumer_reshape_producer_fusion(%arg0 : tensor, #map0 = affine_map<(d0, d1) -> (d0, d1)> func.func @indexed_producer_reshape_consumer_fusion(%arg0 : tensor, - %arg1 : tensor, - %sz0: index, %sz1: index) -> + %arg1 : tensor) -> tensor { %0 = linalg.generic { @@ -278,7 +250,7 @@ func.func @indexed_producer_reshape_consumer_fusion(%arg0 : tensor, %5 = arith.addi %3, %4 : i32 linalg.yield %5 : i32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : tensor into tensor return %1 : tensor } @@ -330,7 +302,8 @@ func.func @reshape_as_consumer_permutation %7 = arith.addi %5, %6 : i32 linalg.yield %7 : i32 } -> tensor<6x4x210xi32> - %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] output_shape [2, 3, 4, 5, 6, 7] : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> + %d = tensor.expand_shape %c [[0, 1], [2], [3, 4, 5]] + : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> return %d : tensor<2x3x4x5x6x7xi32> } @@ -346,9 +319,13 @@ func.func @reshape_as_consumer_permutation // CHECK-SAME: %[[ARG0:.+]]: tensor<210x6x4xi32> // CHECK-SAME: %[[ARG1:.+]]: tensor<210x4xi32> // CHECK-DAG: %[[INIT:.+]] = tensor.empty() -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3, 4], [5]] output_shape [5, 6, 7, 2, 3, 4] : tensor<210x6x4xi32> into tensor<5x6x7x2x3x4xi32> -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [5, 6, 7, 4] : tensor<210x4xi32> into tensor<5x6x7x4xi32> -// CHECK: %[[T3:.+]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1], [2], [3, 4, 5]] output_shape [2, 3, 4, 5, 6, 7] : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> +// CHECK-DAG: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0, 1, 2], [3, 4], [5] +// CHECK-DAG: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0, 1, 2], [3] +// CHECK-DAG: %[[T3:.+]] = tensor.expand_shape %[[INIT]] +// CHECK-SAME: [0, 1], [2], [3, 4, 5] +// CHECK-SAME: : tensor<6x4x210xi32> into tensor<2x3x4x5x6x7xi32> // CHECK: %[[T4:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]]] // CHECK-SAME: ins(%[[T1]], %[[T2]] : tensor<5x6x7x2x3x4xi32>, tensor<5x6x7x4xi32>) @@ -434,8 +411,7 @@ func.func @reshape_as_producer_projected_permutation( #map0 = affine_map<(d0, d1) -> (d0, d1)> #map1 = affine_map<(d0, d1) -> (d1, d0)> func.func @generic_op_reshape_consumer_fusion_projected(%arg0 : tensor, - %arg1 : tensor, - %sz0: index, %sz1: index) -> + %arg1 : tensor) -> tensor { %0 = linalg.generic { @@ -447,7 +423,7 @@ func.func @generic_op_reshape_consumer_fusion_projected(%arg0 : tensor, %1 = arith.mulf %arg3, %arg4 : f32 linalg.yield %1 : f32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : tensor into tensor return %1 : tensor } @@ -457,22 +433,15 @@ func.func @generic_op_reshape_consumer_fusion_projected(%arg0 : tensor, // CHECK: func @generic_op_reshape_consumer_fusion_projected // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor -// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index -// CHECK: %[[C20:.+]] = arith.constant 20 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C20]] : index -// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[VAL_0]], 4, 5, %[[DIM_0]]] : tensor into tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_1]], %[[C20]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[VAL_1]], 4, 5, %[[DIM_2]]] : tensor into tensor -// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_5]], %[[C20]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_4]], %[[VAL_2]], 4, 5] : tensor into tensor +// CHECK: %[[T0:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0, 1, 2], [3] +// CHECK-SAME: tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0, 1, 2], [3] +// CHECK-SAME: tensor into tensor +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP4]], #[[MAP4]], #[[MAP5]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -497,7 +466,6 @@ func.func @no_fuse_dynamic_dims(%arg0: tensor) -> tensor { } -> tensor return %3 : tensor } - // CHECK: func @no_fuse_dynamic_dims // CHECK-SAME: %[[ARG0:.+]]: tensor // CHECK: %[[RESHAPE:.+]] = tensor.collapse_shape %[[ARG0]] @@ -535,8 +503,7 @@ func.func @no_fuse_mismatched_dynamism(%arg0: tensor<2x1xi64>, %arg1: tensor, %b : tensor, %sz0: index, - %sz1: index, %sz2: index, %sz3: index, %sz4: index) + (%a : tensor, %b : tensor) -> (tensor, tensor) { %c:2 = linalg.generic { indexing_maps = [affine_map<(d0, d1, d2) -> (d1, d0, d2)>, @@ -550,8 +517,10 @@ func.func @reshape_as_consumer_permutation_with_multiple_results %1 = arith.addf %arg0, %arg1 : f32 linalg.yield %1, %1 : f32, f32 } -> (tensor, tensor) - %d = tensor.expand_shape %c#0 [[0, 1], [2], [3, 4, 5]] output_shape [%sz0, 2, %sz1, 3, 4, %sz2] : tensor into tensor - %e = tensor.expand_shape %c#1 [[0], [1, 2], [3, 4, 5]] output_shape [%sz3, %sz4, 2, 3, 4, %sz2] : tensor into tensor + %d = tensor.expand_shape %c#0 [[0, 1], [2], [3, 4, 5]] + : tensor into tensor + %e = tensor.expand_shape %c#1 [[0], [1, 2], [3, 4, 5]] + : tensor into tensor return %d, %e : tensor, tensor } // CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d2, d3, d4, d0, d1, d5)> @@ -559,40 +528,17 @@ func.func @reshape_as_consumer_permutation_with_multiple_results // CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d5, d2, d3, d4)> // CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1, d2, d3, d4, d5) -> (d5, d0, d1, d2, d3, d4)> // CHECK: func @reshape_as_consumer_permutation_with_multiple_results -// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: tensor -// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: tensor -// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index, %[[SZ2:.+]]: index, %[[SZ3:.+]]: index, %[[SZ4:.+]]: index -// CHECK: %[[C12:.+]] = arith.constant 12 : index -// CHECK: %[[C2:.+]] = arith.constant 2 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C12]] : index -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C2]] : index -// CHECK: %[[RESHAPE0:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1, 2], [3, 4], [5]] output_shape [3, 4, %[[VAL_0]], %[[VAL_1]], 2, %[[DIM_1]]] : tensor into tensor<3x4x?x?x2x?xf32> -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_3:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_2]], %[[C12]] : index -// CHECK: %[[RESHAPE1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [3, 4, %[[VAL_2]], %[[DIM_3]]] : tensor into tensor<3x4x?x?xf32> -// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_6:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[DIM_7:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor -// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_5]], %[[C2]] : index -// CHECK: %[[VAL_4:.+]] = arith.divui %[[DIM_7]], %[[C12]] : index -// CHECK: %[[RESHAPE2:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2], [3, 4, 5]] output_shape [%[[VAL_3]], 2, %[[DIM_6]], 3, 4, %[[VAL_4]]] : tensor into tensor -// CHECK: %[[DIM_9:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_10:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[DIM_11:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor -// CHECK: %[[VAL_5:.+]] = arith.divui %[[DIM_10]], %[[C2]] : index -// CHECK: %[[VAL_6:.+]] = arith.divui %[[DIM_11]], %[[C12]] : index -// CHECK: %[[RESHAPE3:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2], [3, 4, 5]] output_shape [%[[DIM_9]], %[[VAL_5]], 2, 3, 4, %[[VAL_6]]] : tensor into tensor -// CHECK: %[[GENERIC:.+]]:2 = linalg.generic -// CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]]] -// CHECK-SAME: ins(%[[RESHAPE0]], %[[RESHAPE1]] : -// CHECK-SAME: outs(%[[RESHAPE2]], %[[RESHAPE3]] : -// CHECK: return %[[GENERIC]]#0, %[[GENERIC]]#1 +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: tensor +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: tensor +// CHECK-DAG: %[[RESHAPE0:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3, 4], [5]{{\]}} +// CHECK-DAG: %[[RESHAPE1:.+]] = tensor.expand_shape %[[ARG1]] {{\[}}[0, 1, 2], [3]{{\]}} +// CHECK-DAG: %[[RESHAPE2:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3, 4, 5]{{\]}} +// CHECK-DAG: %[[RESHAPE3:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2], [3, 4, 5]{{\]}} +// CHECK: %[[GENERIC:.+]]:2 = linalg.generic +// CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]]] +// CHECK-SAME: ins(%[[RESHAPE0]], %[[RESHAPE1]] : +// CHECK-SAME: outs(%[[RESHAPE2]], %[[RESHAPE3]] : +// CHECK: return %[[GENERIC]]#0, %[[GENERIC]]#1 // ----- @@ -610,7 +556,7 @@ module { %2 = arith.addf %arg4, %arg5 : f32 linalg.yield %2, %2 : f32, f32 } -> (tensor<512xf32>, tensor<200x512xf32>) - %1 = tensor.expand_shape %0#1 [[0, 1, 2], [3]] output_shape [25, 8, 1, 512] : tensor<200x512xf32> into tensor<25x8x1x512xf32> + %1 = tensor.expand_shape %0#1 [[0, 1, 2], [3]] : tensor<200x512xf32> into tensor<25x8x1x512xf32> return %1 : tensor<25x8x1x512xf32> } } @@ -621,7 +567,7 @@ module { // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: tensor<512xf32> // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: tensor<512xf32> // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: tensor<200x512xf32> -// CHECK: %[[OUTS:.+]] = tensor.expand_shape %[[ARG3]] {{\[\[}}0, 1, 2], [3]] output_shape [25, 8, 1, 512] : tensor<200x512xf32> into tensor<25x8x1x512xf32> +// CHECK: %[[OUTS:.+]] = tensor.expand_shape %[[ARG3]] {{\[}}[0, 1, 2], [3]{{\]}} // CHECK: %[[GENERIC:.+]]:2 = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP0]], #[[MAP0]], #[[MAP1]]] // CHECK-SAME: ins(%[[ARG0]], %[[ARG1]] : @@ -635,9 +581,7 @@ module { #map2 = affine_map<(d0, d1, d2) -> (d0, d1)> func.func @generic_op_reshape_consumer_fusion_reduction(%arg0 : tensor, %arg1 : tensor, - %arg2 : tensor, - %sz0: index, - %sz1: index) -> + %arg2 : tensor) -> tensor { %0 = linalg.generic { @@ -649,7 +593,7 @@ func.func @generic_op_reshape_consumer_fusion_reduction(%arg0 : tensor, %1 = arith.mulf %arg3, %arg4 : f32 linalg.yield %1 : f32 } -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : tensor into tensor return %1 : tensor } @@ -661,18 +605,12 @@ func.func @generic_op_reshape_consumer_fusion_reduction(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index -// CHECK: %[[C20:.+]] = arith.constant 20 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C20]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1, 2], [3]] output_shape [%[[VAL_0]], 4, 5, %[[DIM_0]]] : tensor into tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C20]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_1]], %[[VAL_1]], 4, 5] : tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0, 1, 2], [3] +// CHECK-SAME: tensor into tensor +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel", "reduction"] @@ -712,21 +650,10 @@ func.func @generic_op_reshape_producer_fusion_with_reduction(%arg0 : tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C7:.+]] = arith.constant 7 : index -// CHECK: %[[C8:.+]] = arith.constant 8 : index -// CHECK: %[[C2:.+]] = arith.constant 2 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C2]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C8]] : index -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C7]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1], [2], [3, 4]] output_shape [%[[VAL_0]], 8, 4, %[[VAL_1]], 7] : tensor into tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_1]], %[[C8]] : index -// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_2]], %[[C7]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_2]], 8, %[[VAL_3]], 7] : tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0, 1], [2], [3, 4] +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] +// CHECK-SAME: [0, 1], [2, 3] // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]] // CHECK-SAME: ["parallel", "parallel", "reduction", "parallel", "parallel"] @@ -741,14 +668,12 @@ func.func @generic_op_reshape_producer_fusion_with_reduction(%arg0 : tensor, %arg1 : tensor, - %arg2 : tensor, - %sz0: index, - %sz1: index) -> + %arg2 : tensor) -> tensor { %0 = linalg.add ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) -> tensor - %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] output_shape [%sz0, %sz1, 4, 5] : + %1 = tensor.expand_shape %0 [[0], [1, 2, 3]] : tensor into tensor return %1 : tensor } @@ -758,22 +683,15 @@ func.func @linalg_add_reshape_consumer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK-SAME: %[[SZ0:.+]]: index, %[[SZ1:.+]]: index -// CHECK: %[[C20:.+]] = arith.constant 20 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM_0]], %[[C20]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM]], %[[VAL_0]], 4, 5] : tensor into tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_2]], %[[C20]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_1]], %[[VAL_1]], 4, 5] : tensor into tensor -// CHECK: %[[DIM_4:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor -// CHECK: %[[DIM_5:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_5]], %[[C20]] : index -// CHECK: %[[T3:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0], [1, 2, 3]] output_shape [%[[DIM_4]], %[[VAL_2]], 4, 5] : tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG0]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor +// CHECK: %[[T3:.+]] = tensor.expand_shape %[[ARG2]] +// CHECK-SAME: [0], [1, 2, 3] +// CHECK-SAME: tensor into tensor // CHECK: %[[T4:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[MAP]], #[[MAP]], #[[MAP]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] @@ -803,20 +721,10 @@ func.func @linalg_add_reshape_producer_fusion(%arg0 : tensor, // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]+]]: tensor // CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]+]]: tensor -// CHECK: %[[C8:.+]] = arith.constant 8 : index -// CHECK: %[[C7:.+]] = arith.constant 7 : index -// CHECK: %[[C1:.+]] = arith.constant 1 : index -// CHECK: %[[C0:.+]] = arith.constant 0 : index -// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG1]], %[[C0]] : tensor -// CHECK: %[[DIM_0:.+]] = tensor.dim %[[ARG1]], %[[C1]] : tensor -// CHECK: %[[VAL_0:.+]] = arith.divui %[[DIM]], %[[C7]] : index -// CHECK: %[[VAL_1:.+]] = arith.divui %[[DIM_0]], %[[C8]] : index -// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_0]], 7, %[[VAL_1]], 8] : tensor into tensor -// CHECK: %[[DIM_1:.+]] = tensor.dim %[[ARG2]], %[[C0]] : tensor -// CHECK: %[[DIM_2:.+]] = tensor.dim %[[ARG2]], %[[C1]] : tensor -// CHECK: %[[VAL_2:.+]] = arith.divui %[[DIM_1]], %[[C7]] : index -// CHECK: %[[VAL_3:.+]] = arith.divui %[[DIM_2]], %[[C8]] : index -// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_2]], 7, %[[VAL_3]], 8] : tensor into tensor +// CHECK: %[[T1:.+]] = tensor.expand_shape %[[ARG1]] +// CHECK-SAME: [0, 1], [2, 3] +// CHECK: %[[T2:.+]] = tensor.expand_shape %[[ARG2]] +// CHECK-SAME: [0, 1], [2, 3] // CHECK: %[[T3:.+]] = linalg.generic // CHECK-SAME: indexing_maps = [#[[$MAP]], #[[$MAP]], #[[$MAP]]] // CHECK-SAME: ["parallel", "parallel", "parallel", "parallel"] diff --git a/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir b/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir index 8fb84248c961..4262cd23e746 100644 --- a/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir +++ b/mlir/test/Dialect/Linalg/resolve-shaped-type-result-dims.mlir @@ -199,12 +199,13 @@ func.func @empty_tensor_dim_of_linalg_result(%arg_0 : tensor, // ----- -func.func @dim_reshape_expansion(%arg0 : tensor<6x5x?xf32>, %sz0: index) -> (index, index, index) +func.func @dim_reshape_expansion(%arg0 : tensor<6x5x?xf32>) -> (index, index, index) { %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index %c4 = arith.constant 4 : index - %0 = tensor.expand_shape %arg0 [[0, 1], [2], [3, 4, 5]] output_shape [2, 3, 5, 4, %sz0, 7] : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> + %0 = tensor.expand_shape %arg0 [[0, 1], [2], [3, 4, 5]] + : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> %1 = tensor.dim %0, %c1 : tensor<2x3x5x4x?x7xf32> %2 = tensor.dim %0, %c3 : tensor<2x3x5x4x?x7xf32> %3 = tensor.dim %0, %c4 : tensor<2x3x5x4x?x7xf32> diff --git a/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir b/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir index 31e9fd00cffa..006d6105677e 100644 --- a/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir +++ b/mlir/test/Dialect/Linalg/transform-op-split-reduction.mlir @@ -13,8 +13,8 @@ func.func @matmul_split(%A : tensor<16x256xf32>, %B: tensor<256x32xf32>, %C: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: @matmul_split // CHECK-DAG: %[[ID:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [16, 4, 64] : tensor<16x256xf32> into tensor<16x4x64xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [4, 64, 32] : tensor<256x32xf32> into tensor<4x64x32xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<16x256xf32> into tensor<16x4x64xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<256x32xf32> into tensor<4x64x32xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<16x32x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<16x32x4xf32>) -> tensor<16x32x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]] @@ -65,7 +65,7 @@ func.func @generic_split_1d(%arg0: tensor<32xf32>, %arg1: tensor, %out: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0) -> ()> //CHECK-LABEL: @generic_split_1d // CHECK-DAG: %[[ID:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] output_shape [4, 8] : tensor<32xf32> into tensor<4x8xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] : tensor<32xf32> into tensor<4x8xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<4xf32>) -> tensor<4xf32> // CHECK: %[[G:.*]] = linalg.generic @@ -119,8 +119,8 @@ func.func @generic_split_3d(%input: tensor<32x2xf32>, %input_2: tensor<5x32xf32> // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d // CHECK-DAG: %[[ID:.*]] = arith.constant 0xFF800000 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [4, 8, 2] : tensor<32x2xf32> into tensor<4x8x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 4, 8] : tensor<5x32xf32> into tensor<5x4x8xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<4x8x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x4x8xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} @@ -177,8 +177,8 @@ func.func @generic_split_3d_ninf(%input: tensor<32x2xf32>, %input_2: tensor<5x32 // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d_ninf // CHECK-DAG: %[[ID:.*]] = arith.constant -3.40282347E+38 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [4, 8, 2] : tensor<32x2xf32> into tensor<4x8x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 4, 8] : tensor<5x32xf32> into tensor<5x4x8xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<4x8x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x4x8xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} @@ -218,8 +218,8 @@ func.func @matmul_split(%A : tensor<16x256xf32>, %B: tensor<256x32xf32>, %C: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: @matmul_split // CHECK-DAG: %[[ID:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [16, 64, 4] : tensor<16x256xf32> into tensor<16x64x4xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [64, 4, 32] : tensor<256x32xf32> into tensor<64x4x32xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<16x256xf32> into tensor<16x64x4xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<256x32xf32> into tensor<64x4x32xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<16x32x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<16x32x4xf32>) -> tensor<16x32x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]] @@ -270,7 +270,7 @@ func.func @generic_split_1d(%arg0: tensor<32xf32>, %arg1: tensor, %out: ten // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0) -> ()> //CHECK-LABEL: @generic_split_1d // CHECK-DAG: %[[ID:.*]] = arith.constant 1.000000e+00 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] output_shape [8, 4] : tensor<32xf32> into tensor<8x4xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1]] : tensor<32xf32> into tensor<8x4xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<4xf32>) -> tensor<4xf32> // CHECK: %[[G:.*]] = linalg.generic @@ -324,8 +324,8 @@ func.func @generic_split_3d(%input: tensor<32x2xf32>, %input_2: tensor<5x32xf32> // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d // CHECK-DAG: %[[ID:.*]] = arith.constant 0x7F800000 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [8, 4, 2] : tensor<32x2xf32> into tensor<8x4x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 8, 4] : tensor<5x32xf32> into tensor<5x8x4xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<8x4x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x8x4xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} @@ -382,8 +382,8 @@ func.func @generic_split_3d(%input: tensor<32x2xf32>, %input_2: tensor<5x32xf32> // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)> // CHECK-LABEL: func @generic_split_3d // CHECK-DAG: %[[ID:.*]] = arith.constant 3.40282347E+38 : f32 -// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] output_shape [8, 4, 2] : tensor<32x2xf32> into tensor<8x4x2xf32> -// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] output_shape [5, 8, 4] : tensor<5x32xf32> into tensor<5x8x4xf32> +// CHECK-DAG: %[[I1:.*]] = tensor.expand_shape %{{.*}}[0, 1], [2]] : tensor<32x2xf32> into tensor<8x4x2xf32> +// CHECK-DAG: %[[I2:.*]] = tensor.expand_shape %{{.*}}[0], [1, 2]] : tensor<5x32xf32> into tensor<5x8x4xf32> // CHECK-DAG: %[[INI:.*]] = tensor.empty() : tensor<5x2x4xf32> // CHECK: %[[F:.*]] = linalg.fill ins(%[[ID]] : f32) outs(%[[INI]] : tensor<5x2x4xf32>) -> tensor<5x2x4xf32> // CHECK: %[[G:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "reduction", "parallel", "parallel"]} diff --git a/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir b/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir index d7ff1ded9d93..58d4b21ea2dd 100644 --- a/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir +++ b/mlir/test/Dialect/Linalg/vectorization-with-patterns.mlir @@ -1710,12 +1710,10 @@ module attributes {transform.with_named_sequence} { #map = affine_map<(d0) -> (d0)> // CHECK-LABEL: @not_vectorizable func.func @not_vectorizable(%arg0: tensor<1x?xf32>, %arg1: index, %arg2: index, %arg3: index) -> tensor<1x128xf32> { - %c0 = arith.constant 0 : index %0 = tensor.empty() : tensor<1x128xf32> %1 = scf.for %arg5 = %arg2 to %arg1 step %arg3 iter_args(%arg6 = %0) -> (tensor<1x128xf32>) { %extracted_slice = tensor.extract_slice %arg6[0, 0] [1, %arg1] [1, 1] : tensor<1x128xf32> to tensor - %sz0 = tensor.dim %extracted_slice, %c0 : tensor - %expanded = tensor.expand_shape %extracted_slice [[0, 1]] output_shape [1, %sz0] : tensor into tensor<1x?xf32> + %expanded = tensor.expand_shape %extracted_slice [[0, 1]] : tensor into tensor<1x?xf32> %extracted_slice_0 = tensor.extract_slice %arg0[0, %arg3] [1, %arg2] [1, 1] : tensor<1x?xf32> to tensor %extracted_slice_1 = tensor.extract_slice %expanded[0, %arg3] [1, %arg2] [1, 1] : tensor<1x?xf32> to tensor %2 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel"]} ins(%extracted_slice_0 : tensor) outs(%extracted_slice_1 : tensor) { diff --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir index f442a61dc31e..506ed1f1c10b 100644 --- a/mlir/test/Dialect/MemRef/canonicalize.mlir +++ b/mlir/test/Dialect/MemRef/canonicalize.mlir @@ -13,7 +13,7 @@ func.func @collapse_shape_identity_fold(%arg0 : memref<5xi8>) -> memref<5xi8> { // CHECK-LABEL: expand_shape_identity_fold // CHECK-NEXT: return func.func @expand_shape_identity_fold(%arg0 : memref<5x4xi8>) -> memref<5x4xi8> { - %0 = memref.expand_shape %arg0 [[0], [1]] output_shape [5, 4] : memref<5x4xi8> into memref<5x4xi8> + %0 = memref.expand_shape %arg0 [[0], [1]] : memref<5x4xi8> into memref<5x4xi8> return %0 : memref<5x4xi8> } @@ -23,7 +23,7 @@ func.func @expand_shape_identity_fold(%arg0 : memref<5x4xi8>) -> memref<5x4xi8> // CHECK-NEXT: return func.func @collapse_expand_rank0_cancel(%arg0 : memref<1x1xi8>) -> memref<1x1xi8> { %0 = memref.collapse_shape %arg0 [] : memref<1x1xi8> into memref - %1 = memref.expand_shape %0 [] output_shape [1, 1] : memref into memref<1x1xi8> + %1 = memref.expand_shape %0 [] : memref into memref<1x1xi8> return %1 : memref<1x1xi8> } @@ -455,9 +455,9 @@ func.func @compose_collapse_of_collapse(%arg0 : memref) // ----- func.func @do_not_compose_collapse_of_expand_non_identity_layout( - %arg0: memref>, %sz0: index, %sz1: index) + %arg0: memref>) -> memref> { - %1 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, %sz1] : + %1 = memref.expand_shape %arg0 [[0, 1], [2]] : memref> into memref> %2 = memref.collapse_shape %1 [[0, 1, 2]] : @@ -471,34 +471,35 @@ func.func @do_not_compose_collapse_of_expand_non_identity_layout( // ----- -func.func @compose_expand_of_expand(%arg0 : memref, %sz0: index, %sz1: index, %sz2: index, %sz3: index) +func.func @compose_expand_of_expand(%arg0 : memref) -> memref { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, %sz1] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref into memref - %1 = memref.expand_shape %0 [[0, 1], [2], [3, 4]] output_shape [%sz2, 6, 4, 5, %sz3] : memref into memref + %1 = memref.expand_shape %0 [[0, 1], [2], [3, 4]] + : memref into memref return %1 : memref } // CHECK-LABEL: func @compose_expand_of_expand -// CHECK: memref.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] output_shape [%{{.*}}, 6, 4, 5, %{{.*}}] +// CHECK: memref.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] // CHECK-NOT: memref.expand_shape // ----- func.func @compose_expand_of_expand_of_zero_dim(%arg0 : memref) -> memref<1x1x1xf32> { - %0 = memref.expand_shape %arg0 [] output_shape [1] : memref into memref<1xf32> - %1 = memref.expand_shape %0 [[0, 1, 2]] output_shape [1, 1, 1] + %0 = memref.expand_shape %arg0 [] : memref into memref<1xf32> + %1 = memref.expand_shape %0 [[0, 1, 2]] : memref<1xf32> into memref<1x1x1xf32> return %1 : memref<1x1x1xf32> } // CHECK-LABEL: func @compose_expand_of_expand_of_zero_dim -// CHECK: memref.expand_shape %{{.*}} [] output_shape [1, 1, 1] +// CHECK: memref.expand_shape %{{.*}} [] // CHECK-SAME: memref into memref<1x1x1xf32> // ----- func.func @fold_collapse_of_expand(%arg0 : memref<12x4xf32>) -> memref<12x4xf32> { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [3, 4, 4] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref<12x4xf32> into memref<3x4x4xf32> %1 = memref.collapse_shape %0 [[0, 1], [2]] : memref<3x4x4xf32> into memref<12x4xf32> @@ -509,9 +510,9 @@ func.func @fold_collapse_of_expand(%arg0 : memref<12x4xf32>) -> memref<12x4xf32> // ----- -func.func @fold_collapse_collapse_of_expand(%arg0 : memref, %sz0: index, %sz1: index) +func.func @fold_collapse_collapse_of_expand(%arg0 : memref) -> memref { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, %sz1] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref into memref %1 = memref.collapse_shape %0 [[0, 1], [2]] : memref into memref @@ -524,7 +525,7 @@ func.func @fold_collapse_collapse_of_expand(%arg0 : memref, %sz0: index func.func @fold_memref_expand_cast(%arg0 : memref) -> memref<2x4x4xf32> { %0 = memref.cast %arg0 : memref to memref<8x4xf32> - %1 = memref.expand_shape %0 [[0, 1], [2]] output_shape [2, 4, 4] + %1 = memref.expand_shape %0 [[0, 1], [2]] : memref<8x4xf32> into memref<2x4x4xf32> return %1 : memref<2x4x4xf32> } @@ -980,10 +981,10 @@ func.func @memref_realloc_dead(%src : memref<2xf32>, %v : f32) -> memref<2xf32>{ // CHECK-SAME: %[[m:.*]]: memref, 3> // CHECK: %[[casted:.*]] = memref.cast %[[m]] : memref, 3> to memref, 3>, %sz0: index) +func.func @collapse_expand_fold_to_cast(%m: memref, 3>) -> (memref) { - %0 = memref.expand_shape %m [[0, 1]] output_shape [1, %sz0] + %0 = memref.expand_shape %m [[0, 1]] : memref, 3> into memref<1x?xf32, 3> %1 = memref.collapse_shape %0 [[0, 1]] : memref<1x?xf32, 3> into memref diff --git a/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir b/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir index fdfaa72168d1..28b700430059 100644 --- a/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir +++ b/mlir/test/Dialect/MemRef/expand-strided-metadata.mlir @@ -421,11 +421,10 @@ func.func @simplify_expand_shape( %base: memref>, %offset0: index, %offset1: index, %offset2: index, %size0: index, %size1: index, %size2: index, - %stride0: index, %stride1: index, %stride2: index, - %sz0: index, %sz1: index) + %stride0: index, %stride1: index, %stride2: index) -> memref> { - %subview = memref.expand_shape %base [[0, 1, 2, 3],[4, 5, 6, 7]] output_shape [%sz0, 7, 8, 9, 10, 2, %sz1, 3] : + %subview = memref.expand_shape %base[[0, 1, 2, 3],[4, 5, 6, 7]] : memref> into memref> @@ -492,7 +491,7 @@ func.func @extract_strided_metadata_of_expand_shape_all_static( index, index, index, index, index, index, index, index, index, index) { - %expand_shape = memref.expand_shape %arg[[0, 1, 2], [3, 4]] output_shape [3, 5, 2, 2, 2] : + %expand_shape = memref.expand_shape %arg[[0, 1, 2], [3, 4]] : memref<30x4xi16> into memref<3x5x2x2x2xi16> %base, %offset, %sizes:5, %strides:5 = memref.extract_strided_metadata %expand_shape : @@ -596,13 +595,12 @@ func.func @extract_strided_metadata_of_expand_shape_all_dynamic( %base: memref>, %offset0: index, %offset1: index, %offset2: index, %size0: index, %size1: index, %size2: index, - %stride0: index, %stride1: index, %stride2: index, - %sz0: index, %sz1: index) + %stride0: index, %stride1: index, %stride2: index) -> (memref, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index, index) { - %subview = memref.expand_shape %base[[0, 1, 2, 3],[4, 5, 6, 7]] output_shape [%sz0, 7, 8, 9, 10, 2, %sz1, 3] : + %subview = memref.expand_shape %base[[0, 1, 2, 3],[4, 5, 6, 7]] : memref> into memref> @@ -645,7 +643,7 @@ func.func @extract_strided_metadata_of_expand_shape_all_static_0_rank( index, index, index, index, index, index, index, index, index, index) { - %expand_shape = memref.expand_shape %arg[] output_shape [1, 1, 1, 1, 1] : + %expand_shape = memref.expand_shape %arg[] : memref> into memref<1x1x1x1x1xi16, strided<[1,1,1,1,1], offset: ?>> %base, %offset, %sizes:5, %strides:5 = memref.extract_strided_metadata %expand_shape : @@ -1515,4 +1513,4 @@ func.func @zero_sized_memred(%arg0: f32) -> (memref, index,index,index) %sizes, %strides : memref, index, index, index -} +} \ No newline at end of file diff --git a/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir b/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir index 254cd4015eed..5b853a6cc5a3 100644 --- a/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir +++ b/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir @@ -412,7 +412,7 @@ func.func @fold_static_stride_subview_with_affine_load_store(%arg0 : memref<12x3 // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape // CHECK-SAME: (%[[ARG0:.*]]: memref<12x32xf32>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index) -> f32 { func.func @fold_static_stride_subview_with_affine_load_store_expand_shape(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [2, 6, 32] : memref<12x32xf32> into memref<2x6x32xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref<12x32xf32> into memref<2x6x32xf32> %1 = affine.load %0[%arg1, %arg2, %arg3] : memref<2x6x32xf32> return %1 : f32 } @@ -458,7 +458,7 @@ func.func @fold_dynamic_size_collapse_shape_with_affine_load(%arg0 : memref, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index, %[[ARG4:.*]]: index) -> f32 { func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_3d(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1, 2], [3]] output_shape [2, 2, 3, 32] : memref<12x32xf32> into memref<2x2x3x32xf32> + %0 = memref.expand_shape %arg0 [[0, 1, 2], [3]] : memref<12x32xf32> into memref<2x2x3x32xf32> %1 = affine.load %0[%arg1, %arg2, %arg3, %arg4] : memref<2x2x3x32xf32> return %1 : f32 } @@ -469,17 +469,15 @@ func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_3d(%ar // ----- // CHECK-LABEL: fold_dynamic_subview_with_memref_load_store_expand_shape -// CHECK-SAME: (%[[ARG0:.*]]: memref<16x?xf32, strided<[16, 1]>>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[SZ0:.*]]: index) -func.func @fold_dynamic_subview_with_memref_load_store_expand_shape(%arg0 : memref<16x?xf32, strided<[16, 1]>>, %arg1 : index, %arg2 : index, %sz0: index) -> f32 { +func.func @fold_dynamic_subview_with_memref_load_store_expand_shape(%arg0 : memref<16x?xf32, strided<[16, 1]>>, %arg1 : index, %arg2 : index) -> f32 { %c0 = arith.constant 0 : index - %expand_shape = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 16, %sz0, 1] : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> + %expand_shape = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> %0 = memref.load %expand_shape[%c0, %arg1, %arg2, %c0] : memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> return %0 : f32 } -// CHECK: %[[C0:.*]] = arith.constant 0 : index -// CHECK: %[[EXPAND_SHAPE:.*]] = memref.expand_shape %[[ARG0]] {{\[\[}}0, 1], [2, 3]] output_shape [1, 16, %[[SZ0]], 1] : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> -// CHECK: %[[VAL_0:.*]] = memref.load %[[EXPAND_SHAPE]][%[[C0]], %[[ARG1]], %[[ARG2]], %[[C0]]] : memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> -// CHECK: return %[[VAL_0]] : f32 +// CHECK: %[[EXPAND_SHAPE:.+]] = memref.expand_shape {{.+}} : memref<16x?xf32, strided<[16, 1]>> into memref<1x16x?x1xf32, strided<[256, 16, 1, 1]>> +// CHECK: %[[LOAD:.+]] = memref.load %[[EXPAND_SHAPE]] +// CHECK: return %[[LOAD]] // ----- @@ -488,7 +486,7 @@ func.func @fold_dynamic_subview_with_memref_load_store_expand_shape(%arg0 : memr // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape // CHECK-SAME: (%[[ARG0:.*]]: memref<1024x1024xf32>, %[[ARG1:.*]]: memref<1xf32>, %[[ARG2:.*]]: index) func.func @fold_static_stride_subview_with_affine_load_store_expand_shape(%arg0: memref<1024x1024xf32>, %arg1: memref<1xf32>, %arg2: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 1024, 1024, 1] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> affine.for %arg3 = 0 to 1 { affine.for %arg4 = 0 to 1024 { affine.for %arg5 = 0 to 1020 { @@ -517,7 +515,7 @@ func.func @fold_static_stride_subview_with_affine_load_store_expand_shape(%arg0: // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape_when_access_index_is_an_expression // CHECK-SAME: (%[[ARG0:.*]]: memref<1024x1024xf32>, %[[ARG1:.*]]: memref<1xf32>, %[[ARG2:.*]]: index) func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_when_access_index_is_an_expression(%arg0: memref<1024x1024xf32>, %arg1: memref<1xf32>, %arg2: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 1024, 1024, 1] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> affine.for %arg3 = 0 to 1 { affine.for %arg4 = 0 to 1024 { affine.for %arg5 = 0 to 1020 { @@ -546,7 +544,7 @@ func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_when_a // CHECK-LABEL: fold_static_stride_subview_with_affine_load_store_expand_shape_with_constant_access_index // CHECK-SAME: (%[[ARG0:.*]]: memref<1024x1024xf32>, %[[ARG1:.*]]: memref<1xf32>, %[[ARG2:.*]]: index) func.func @fold_static_stride_subview_with_affine_load_store_expand_shape_with_constant_access_index(%arg0: memref<1024x1024xf32>, %arg1: memref<1xf32>, %arg2: index) -> f32 { - %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [1, 1024, 1024, 1] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> + %0 = memref.expand_shape %arg0 [[0, 1], [2, 3]] : memref<1024x1024xf32> into memref<1x1024x1024x1xf32> %cst = arith.constant 0 : index affine.for %arg3 = 0 to 1 { affine.for %arg4 = 0 to 1024 { diff --git a/mlir/test/Dialect/MemRef/invalid.mlir b/mlir/test/Dialect/MemRef/invalid.mlir index 21bbffc5b5a9..1aef417549d9 100644 --- a/mlir/test/Dialect/MemRef/invalid.mlir +++ b/mlir/test/Dialect/MemRef/invalid.mlir @@ -392,9 +392,9 @@ func.func @copy_different_eltype(%arg0: memref<2xf32>, %arg1: memref<2xf16>) { // ----- -func.func @expand_shape(%arg0: memref, %sz0: index, %sz1: index) { +func.func @expand_shape(%arg0: memref) { // expected-error @+1 {{invalid number of reassociation groups: found 1, expected 2}} - %0 = memref.expand_shape %arg0 [[0, 1]] output_shape [%sz0, 5, %sz1] : memref into memref + %0 = memref.expand_shape %arg0 [[0, 1]] : memref into memref return } @@ -402,7 +402,7 @@ func.func @expand_shape(%arg0: memref, %sz0: index, %sz1: index) { func.func @expand_shape(%arg0: memref) { // expected-error @+1 {{rank 0 memrefs can only be extended/collapsed with/from ones}} - %0 = memref.expand_shape %arg0 [] output_shape [1, 2] : memref into memref<1x2xf32> + %0 = memref.expand_shape %arg0 [] : memref into memref<1x2xf32> return } @@ -415,9 +415,9 @@ func.func @collapse_shape_out_of_bounds(%arg0: memref) { // ----- -func.func @expand_shape_out_of_bounds(%arg0: memref, %sz0: index) { +func.func @expand_shape_out_of_bounds(%arg0: memref) { // expected-error @+1 {{op reassociation index 2 is out of bounds}} - %0 = memref.expand_shape %arg0 [[0, 1, 2]] output_shape [4, %sz0] : memref into memref<4x?xf32> + %0 = memref.expand_shape %arg0 [[0, 1, 2]] : memref into memref<4x?xf32> } // ----- @@ -425,7 +425,7 @@ func.func @expand_shape_out_of_bounds(%arg0: memref, %sz0: index) { func.func @expand_shape_invalid_result_layout( %arg0: memref<30x20xf32, strided<[4000, 2], offset: 100>>) { // expected-error @+1 {{expected expanded type to be 'memref<2x15x20xf32, strided<[60000, 4000, 2], offset: 100>>' but found 'memref<2x15x20xf32, strided<[5000, 4000, 2], offset: 100>>'}} - %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [2, 15, 20] : + %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref<30x20xf32, strided<[4000, 2], offset: 100>> into memref<2x15x20xf32, strided<[5000, 4000, 2], offset: 100>> } @@ -462,7 +462,7 @@ func.func @collapse_shape_invalid_reassociation_expansion(%arg0: memref) // like this. Verify that a sensible error is emitted in this case. func.func @expand_shape_invalid_reassociation(%arg0: memref<2x3x1xf32>) { // expected-error @+1 {{'memref.expand_shape' op has source rank 3 and result rank 2. This is not an expansion (3 > 2)}} - %0 = memref.expand_shape %arg0 [[0], [1], [1]] output_shape [2, 3] : + %0 = memref.expand_shape %arg0 [[0], [1], [1]] : memref<2x3x1xf32> into memref<2x3xf32> } @@ -495,10 +495,20 @@ func.func @collapse_shape_wrong_collapsed_type(%arg0: memref) { // ----- +func.func @expand_shape_illegal_dynamic_memref + (%arg0: memref) -> memref { + // expected-error @+1 {{at most one dimension in a reassociation group may be dynamic}} + %0 = memref.expand_shape %arg0 [[0], [1], [2, 3, 4]] + : memref into memref + return %0 : memref +} + +// ----- + func.func @expand_shape_illegal_static_memref (%arg0: memref<2x3x20xf32>) -> memref<2x3x2x4x5xf32> { // expected-error @+1 {{collapsed dim size (20) must equal reassociation group size (40)}} - %0 = memref.expand_shape %arg0 [[0], [1], [2, 3, 4]] output_shape [2, 3, 2, 4, 5] + %0 = memref.expand_shape %arg0 [[0], [1], [2, 3, 4]] : memref<2x3x20xf32> into memref<2x3x2x4x5xf32> return %0 : memref<2x3x2x4x5xf32> } @@ -515,30 +525,30 @@ func.func @collapse_shape_illegal_static_memref // ----- -func.func @expand_shape_illegal_mixed_memref(%arg0 : memref, %sz0: index) +func.func @expand_shape_illegal_mixed_memref(%arg0 : memref) -> memref { // expected-error @+1 {{collapsed dim (1) must be dynamic if and only if reassociation group is dynamic}} - %0 = memref.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, 5] + %0 = memref.expand_shape %arg0 [[0, 1], [2]] : memref into memref return %0 : memref } // ----- -func.func @expand_shape_illegal_mixed_memref_2(%arg0 : memref, %sz0: index) +func.func @expand_shape_illegal_mixed_memref_2(%arg0 : memref) -> memref { // expected-error @+1 {{collapsed dim (1) must be dynamic if and only if reassociation group is dynamic}} - %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [%sz0, 4, 5] + %0 = memref.expand_shape %arg0 [[0], [1, 2]] : memref into memref return %0 : memref } // ----- -func.func @expand_shape_invalid_static_dim_size(%arg0 : memref, %sz0: index) +func.func @expand_shape_invalid_static_dim_size(%arg0 : memref) -> memref { // expected-error @+1 {{collapsed dim size (21) must equal reassociation group size (20)}} - %0 = memref.expand_shape %arg0 [[0], [1, 2]] output_shape [%sz0, 4, 5] + %0 = memref.expand_shape %arg0 [[0], [1, 2]] : memref into memref return %0 : memref } diff --git a/mlir/test/Dialect/MemRef/ops.mlir b/mlir/test/Dialect/MemRef/ops.mlir index 60fb0ffeee24..2d69904f27db 100644 --- a/mlir/test/Dialect/MemRef/ops.mlir +++ b/mlir/test/Dialect/MemRef/ops.mlir @@ -106,9 +106,9 @@ func.func @expand_collapse_shape_static( %0 = memref.collapse_shape %arg0 [[0, 1], [2]] : memref<3x4x5xf32> into memref<12x5xf32> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [3, 4, 5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] // CHECK-SAME: memref<12x5xf32> into memref<3x4x5xf32> - %r0 = memref.expand_shape %0 [[0, 1], [2]] output_shape [3, 4, 5] : + %r0 = memref.expand_shape %0 [[0, 1], [2]] : memref<12x5xf32> into memref<3x4x5xf32> // CHECK: memref.collapse_shape {{.*}} {{\[}}[0], [1, 2]] @@ -116,9 +116,9 @@ func.func @expand_collapse_shape_static( %1 = memref.collapse_shape %arg0 [[0], [1, 2]] : memref<3x4x5xf32> into memref<3x20xf32> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] output_shape [3, 4, 5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] // CHECK-SAME: memref<3x20xf32> into memref<3x4x5xf32> - %r1 = memref.expand_shape %1 [[0], [1, 2]] output_shape [3, 4, 5] : + %r1 = memref.expand_shape %1 [[0], [1, 2]] : memref<3x20xf32> into memref<3x4x5xf32> // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1, 2]] @@ -126,29 +126,29 @@ func.func @expand_collapse_shape_static( %2 = memref.collapse_shape %arg0 [[0, 1, 2]] : memref<3x4x5xf32> into memref<60xf32> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1, 2]] output_shape [3, 4, 5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1, 2]] // CHECK-SAME: memref<60xf32> into memref<3x4x5xf32> - %r2 = memref.expand_shape %2 [[0, 1, 2]] output_shape [3, 4, 5] : + %r2 = memref.expand_shape %2 [[0, 1, 2]] : memref<60xf32> into memref<3x4x5xf32> -// CHECK: memref.expand_shape {{.*}} [] output_shape [1, 1] +// CHECK: memref.expand_shape {{.*}} [] // CHECK-SAME: memref into memref<1x1xf32> - %r5 = memref.expand_shape %arg5 [] output_shape [1, 1] : + %r5 = memref.expand_shape %arg5 [] : memref into memref<1x1xf32> // Reshapes with a custom layout map. -// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] output_shape [30, 4, 5] - %l0 = memref.expand_shape %arg3 [[0], [1, 2]] output_shape [30, 4, 5] : +// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] + %l0 = memref.expand_shape %arg3 [[0], [1, 2]] : memref<30x20xf32, strided<[4000, 2], offset: 100>> into memref<30x4x5xf32, strided<[4000, 10, 2], offset: 100>> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [2, 15, 20] - %l1 = memref.expand_shape %arg3 [[0, 1], [2]] output_shape [2, 15, 20] : +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] + %l1 = memref.expand_shape %arg3 [[0, 1], [2]] : memref<30x20xf32, strided<[4000, 2], offset: 100>> into memref<2x15x20xf32, strided<[60000, 4000, 2], offset: 100>> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] output_shape [1, 1, 5] - %r4 = memref.expand_shape %arg4 [[0], [1, 2]] output_shape [1, 1, 5] : +// CHECK: memref.expand_shape {{.*}} {{\[}}[0], [1, 2]] + %r4 = memref.expand_shape %arg4 [[0], [1, 2]] : memref<1x5xf32, strided<[5, 1], offset: ?>> into memref<1x1x5xf32, strided<[5, 5, 1], offset: ?>> @@ -164,9 +164,9 @@ func.func @expand_collapse_shape_static( memref<2049xi64, strided<[?], offset: ?>> // Reshapes that expand and collapse back a contiguous buffer with some 1's. -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2], [3, 4]] // CHECK-SAME: memref<3x4x5xf32> into memref<1x3x4x1x5xf32> - %3 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5]: + %3 = memref.expand_shape %arg0 [[0, 1], [2], [3, 4]] : memref<3x4x5xf32> into memref<1x3x4x1x5xf32> // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1], [2], [3, 4]] @@ -176,18 +176,15 @@ func.func @expand_collapse_shape_static( // Reshapes on tensors. // CHECK: tensor.expand_shape {{.*}}: tensor<3x4x5xf32> into tensor<1x3x4x1x5xf32> - %t0 = tensor.expand_shape %arg1 [[0, 1], [2], [3, 4]] output_shape [1, 3, 4, 1, 5] : + %t0 = tensor.expand_shape %arg1 [[0, 1], [2], [3, 4]] : tensor<3x4x5xf32> into tensor<1x3x4x1x5xf32> // CHECK: tensor.collapse_shape {{.*}}: tensor<1x3x4x1x5xf32> into tensor<3x4x5xf32> %rt0 = tensor.collapse_shape %t0 [[0, 1], [2], [3, 4]] : tensor<1x3x4x1x5xf32> into tensor<3x4x5xf32> -// CHECK: tensor.dim %arg2, {{.*}} : tensor<3x?x5xf32> // CHECK: tensor.expand_shape {{.*}}: tensor<3x?x5xf32> into tensor<1x3x?x1x5xf32> - %c1 = arith.constant 1 : index - %sz1 = tensor.dim %arg2, %c1 : tensor<3x?x5xf32> - %t1 = tensor.expand_shape %arg2 [[0, 1], [2], [3, 4]] output_shape [1, 3, %sz1, 1, 5] : + %t1 = tensor.expand_shape %arg2 [[0, 1], [2], [3, 4]] : tensor<3x?x5xf32> into tensor<1x3x?x1x5xf32> // CHECK: tensor.collapse_shape {{.*}}: tensor<1x3x?x1x5xf32> into tensor<1x?x5xf32> @@ -200,18 +197,15 @@ func.func @expand_collapse_shape_static( func.func @expand_collapse_shape_dynamic(%arg0: memref, %arg1: memref>, %arg2: memref>, - %arg3: memref>, - %arg4: index, - %arg5: index, - %arg6: index) { + %arg3: memref>) { // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]] // CHECK-SAME: memref into memref %0 = memref.collapse_shape %arg0 [[0, 1], [2]] : memref into memref -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [%arg4, 4, %arg5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] // CHECK-SAME: memref into memref - %r0 = memref.expand_shape %0 [[0, 1], [2]] output_shape [%arg4, 4, %arg5] : + %r0 = memref.expand_shape %0 [[0, 1], [2]] : memref into memref // CHECK: memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]] @@ -220,9 +214,9 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, memref> into memref> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [%arg4, 4, %arg5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] // CHECK-SAME: memref> into memref> - %r1 = memref.expand_shape %1 [[0, 1], [2]] output_shape [%arg4, 4, %arg5] : + %r1 = memref.expand_shape %1 [[0, 1], [2]] : memref> into memref> @@ -232,9 +226,9 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, memref> into memref> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] output_shape [%arg4, 4, %arg5] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1], [2]] // CHECK-SAME: memref> into memref> - %r2 = memref.expand_shape %2 [[0, 1], [2]] output_shape [%arg4, 4, %arg5] : + %r2 = memref.expand_shape %2 [[0, 1], [2]] : memref> into memref> @@ -244,9 +238,9 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, memref> into memref> -// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1]] output_shape [%arg6, 42] +// CHECK: memref.expand_shape {{.*}} {{\[}}[0, 1]] // CHECK-SAME: memref> into memref - %r3 = memref.expand_shape %3 [[0, 1]] output_shape [%arg6, 42] : + %r3 = memref.expand_shape %3 [[0, 1]] : memref> into memref return } @@ -254,12 +248,12 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref, func.func @expand_collapse_shape_zero_dim(%arg0 : memref<1x1xf32>, %arg1 : memref) -> (memref, memref<1x1xf32>) { %0 = memref.collapse_shape %arg0 [] : memref<1x1xf32> into memref - %1 = memref.expand_shape %0 [] output_shape [1, 1] : memref into memref<1x1xf32> + %1 = memref.expand_shape %0 [] : memref into memref<1x1xf32> return %0, %1 : memref, memref<1x1xf32> } // CHECK-LABEL: func @expand_collapse_shape_zero_dim // CHECK: memref.collapse_shape %{{.*}} [] : memref<1x1xf32> into memref -// CHECK: memref.expand_shape %{{.*}} [] output_shape [1, 1] : memref into memref<1x1xf32> +// CHECK: memref.expand_shape %{{.*}} [] : memref into memref<1x1xf32> func.func @collapse_shape_to_dynamic (%arg0: memref) -> memref { @@ -276,18 +270,16 @@ func.func @collapse_shape_to_dynamic // CHECK-LABEL: func @expand_collapse_shape_transposed_layout func.func @expand_collapse_shape_transposed_layout( %m0: memref>, - %m1: memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>>, - %sz0: index, - %sz1: index) { + %m1: memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>>) { - %r0 = memref.expand_shape %m0 [[0], [1, 2]] output_shape [%sz0, %sz1, 5] : + %r0 = memref.expand_shape %m0 [[0], [1, 2]] : memref> into memref> %rr0 = memref.collapse_shape %r0 [[0], [1, 2]] : memref> into memref> - %r1 = memref.expand_shape %m1 [[0, 1], [2], [3, 4]] output_shape [2, 2, 5, 2, 3] : + %r1 = memref.expand_shape %m1 [[0, 1], [2], [3, 4]] : memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>> into memref<2x2x5x2x3xf32, strided<[2, 1, ?, 3000, 1000], offset: 0>> %rr1 = memref.collapse_shape %r1 [[0, 1], [2], [3, 4]] : diff --git a/mlir/test/Dialect/MemRef/runtime-verification.mlir b/mlir/test/Dialect/MemRef/runtime-verification.mlir index 28777a3e8867..4d7fcf6ac7cb 100644 --- a/mlir/test/Dialect/MemRef/runtime-verification.mlir +++ b/mlir/test/Dialect/MemRef/runtime-verification.mlir @@ -2,14 +2,13 @@ // CHECK-LABEL: func @expand_shape( // CHECK-SAME: %[[m:.*]]: memref -// CHECK-SAME: %[[sz0:.*]]: index // CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[c5:.*]] = arith.constant 5 : index // CHECK-DAG: %[[dim:.*]] = memref.dim %[[m]], %[[c0]] // CHECK: %[[mod:.*]] = arith.remsi %[[dim]], %[[c5]] // CHECK: %[[cmpi:.*]] = arith.cmpi eq, %[[mod]], %[[c0]] // CHECK: cf.assert %[[cmpi]], "ERROR: Runtime op verification failed -func.func @expand_shape(%m: memref, %sz0: index) -> memref { - %0 = memref.expand_shape %m [[0, 1]] output_shape [%sz0, 5] : memref into memref +func.func @expand_shape(%m: memref) -> memref { + %0 = memref.expand_shape %m [[0, 1]] : memref into memref return %0 : memref } diff --git a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir index c96f9c31443d..edb53fa024c2 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir @@ -12,7 +12,7 @@ // // CHECK-ROUND-LABEL: func.func @sparse_expand( // CHECK-ROUND-SAME: %[[A:.*]]: tensor<100xf64, #sparse{{[0-9]*}}>) -> tensor<10x10xf64, #sparse{{[0-9]*}}> -// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] output_shape [10, 10] : tensor<100xf64, #sparse{{[0-9]*}}> into tensor<10x10xf64, #sparse{{[0-9]*}}> +// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] : tensor<100xf64, #sparse{{[0-9]*}}> into tensor<10x10xf64, #sparse{{[0-9]*}}> // CHECK-ROUND: return %[[E]] : tensor<10x10xf64, #sparse{{[0-9]*}}> // // CHECK-LABEL: func.func @sparse_expand( @@ -39,7 +39,7 @@ // CHECK: return %[[NT1]] : tensor<10x10xf64, #sparse{{[0-9]*}}> // func.func @sparse_expand(%arg0: tensor<100xf64, #SparseVector>) -> tensor<10x10xf64, #SparseMatrix> { - %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [10, 10] : + %0 = tensor.expand_shape %arg0 [[0, 1]] : tensor<100xf64, #SparseVector> into tensor<10x10xf64, #SparseMatrix> return %0 : tensor<10x10xf64, #SparseMatrix> } @@ -94,8 +94,8 @@ func.func @sparse_collapse(%arg0: tensor<10x10xf64, #SparseMatrix>) -> tensor<10 // roundtrip: // // CHECK-ROUND-LABEL: func.func @dynamic_sparse_expand( -// CHECK-ROUND-SAME: %[[A:.*]]: tensor, %[[SZ0:.*]]: index) -> tensor -// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] output_shape [%[[SZ0]], 10] : tensor into tensor +// CHECK-ROUND-SAME: %[[A:.*]]: tensor) -> tensor +// CHECK-ROUND: %[[E:.*]] = tensor.expand_shape %[[A]] {{\[\[}}0, 1]] : tensor into tensor // CHECK-ROUND: return %[[E]] : tensor // // CHECK-LABEL: func.func @dynamic_sparse_expand( @@ -127,8 +127,8 @@ func.func @sparse_collapse(%arg0: tensor<10x10xf64, #SparseMatrix>) -> tensor<10 // CHECK-NOT: sparse_tensor.convert // CHECK: return %[[NT1]] : tensor // -func.func @dynamic_sparse_expand(%arg0: tensor, %sz0: index) -> tensor { - %0 = tensor.expand_shape %arg0 [[0, 1]] output_shape [%sz0, 10] : +func.func @dynamic_sparse_expand(%arg0: tensor) -> tensor { + %0 = tensor.expand_shape %arg0 [[0, 1]] : tensor into tensor return %0 : tensor } diff --git a/mlir/test/Dialect/Tensor/bufferize.mlir b/mlir/test/Dialect/Tensor/bufferize.mlir index 4f553adcc500..815bc383af95 100644 --- a/mlir/test/Dialect/Tensor/bufferize.mlir +++ b/mlir/test/Dialect/Tensor/bufferize.mlir @@ -367,14 +367,11 @@ func.func @tensor.insert(%t1: tensor<5xf32>, %idx1: index, %f: f32) -> tensor<5x // CHECK-LABEL: func @tensor.expand_shape( // CHECK-SAME: %[[t1:.*]]: tensor -func.func @tensor.expand_shape(%t1: tensor, %sz0: index) -> tensor<2x?x10xf32> { +func.func @tensor.expand_shape(%t1: tensor) -> tensor<2x?x10xf32> { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref - // CHECK: %[[C0:.*]] = arith.constant 0 : index - // CHECK: %[[DIM:.*]] = memref.dim %[[m1]], %[[C0]] : memref - // CHECK: %[[C2:.*]] = arith.constant 2 : index - // CHECK: %[[VAL_1:.*]] = arith.divui %[[DIM]], %[[C2]] : index - // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] {{\[\[}}0, 1], [2]] output_shape [2, %[[VAL_1]], 10] : memref into memref<2x?x10xf32> - %0 = tensor.expand_shape %t1 [[0, 1], [2]] output_shape [2, %sz0, 10] + // CHECK: %[[expanded:.*]] = memref.expand_shape %[[m1]] [ + // CHECK-SAME: [0, 1], [2]] : memref into memref<2x?x10xf32> + %0 = tensor.expand_shape %t1 [[0, 1], [2]] : tensor into tensor<2x?x10xf32> // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] @@ -387,15 +384,14 @@ func.func @tensor.expand_shape(%t1: tensor, %sz0: index) -> tensor<2x? // CHECK-LABEL: func @tensor.expand_shape_of_slice( // CHECK-SAME: %[[t1:.*]]: tensor func.func @tensor.expand_shape_of_slice( - %t1: tensor, %o1: index, %s1: index, %sz0: index) -> tensor { + %t1: tensor, %o1: index, %s1: index) -> tensor { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}, 5] [%{{.*}}, 10] [1, 1] : memref to memref> %0 = tensor.extract_slice %t1[%o1, 5][%s1, 10][1, 1] : tensor to tensor - // CHECK: %[[C7:.*]] = arith.constant 7 : index - // CHECK: %[[VAL_1:.*]] = arith.divui %{{.*}}, %[[C7]] : index - // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] {{\[\[}}0, 1], [2, 3]] output_shape [%[[VAL_1]], 7, 2, 5] : memref> into memref> - %1 = tensor.expand_shape %0 [[0, 1], [2, 3]] output_shape [%sz0, 7, 2, 5] : + // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [ + // CHECK-SAME: [0, 1], [2, 3]] : memref> into memref> + %1 = tensor.expand_shape %0 [[0, 1], [2, 3]] : tensor into tensor // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] // CHECK: return %[[r]] @@ -411,8 +407,8 @@ func.func @tensor.expand_shape_of_scalar_slice( // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] : memref // CHECK: %[[subview:.*]] = memref.subview %[[m1]][%{{.*}}] [1] [1] : memref to memref> %0 = tensor.extract_slice %t1[%o1][1][1] : tensor to tensor - // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [] output_shape [1] : memref into memref<1xf32, strided<[1], offset: ?>> - %1 = tensor.expand_shape %0 [] output_shape [1] : tensor into tensor<1xf32> + // CHECK: %[[expanded:.*]] = memref.expand_shape %[[subview]] [] : memref into memref<1xf32, strided<[1], offset: ?>> + %1 = tensor.expand_shape %0 [] : tensor into tensor<1xf32> // CHECK: %[[r:.*]] = bufferization.to_tensor %[[expanded]] // CHECK: return %[[r]] return %1 : tensor<1xf32> diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index 145ba8fcd5eb..751c57eacd7a 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -4,7 +4,7 @@ // CHECK-LABEL: expand_shape_identity_fold // CHECK-NEXT: return func.func @expand_shape_identity_fold(%arg0 : tensor<5xf32>) -> tensor<5xf32> { - %0 = tensor.expand_shape %arg0 [[0]] output_shape [5] : tensor<5xf32> into tensor<5xf32> + %0 = tensor.expand_shape %arg0 [[0]] : tensor<5xf32> into tensor<5xf32> return %0 : tensor<5xf32> } @@ -13,7 +13,7 @@ func.func @expand_shape_identity_fold(%arg0 : tensor<5xf32>) -> tensor<5xf32> { // CHECK-LABEL: expand_shape_rank0_identity_fold // CHECK-NEXT: return func.func @expand_shape_rank0_identity_fold(%arg0 : tensor) -> tensor { - %0 = tensor.expand_shape %arg0 [] output_shape [] : tensor into tensor + %0 = tensor.expand_shape %arg0 [] : tensor into tensor return %0 : tensor } @@ -1051,28 +1051,29 @@ func.func @fold_overlapping_insert(%input : tensor, %slice1: tensor<4 // ----- -func.func @compose_expand_of_expand(%arg0 : tensor, %arg1: index, %arg2: index, %arg3: index, %arg4: index) +func.func @compose_expand_of_expand(%arg0 : tensor) -> tensor { - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [%arg1, 4, %arg2] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] : tensor into tensor - %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4]] output_shape [%arg3, 6, 4, %arg4, 5] : tensor into tensor + %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4]] + : tensor into tensor return %1 : tensor } // CHECK-LABEL: compose_expand_of_expand -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] output_shape [%arg3, 6, 4, %arg4, 5] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2], [3, 4]] // CHECK-NOT: tensor.expand_shape // ----- func.func @compose_expand_of_expand_of_zero_dim(%arg0 : tensor) -> tensor<1x1x1xf32> { - %0 = tensor.expand_shape %arg0 [] output_shape [1] : tensor into tensor<1xf32> - %1 = tensor.expand_shape %0 [[0, 1, 2]] output_shape [1, 1, 1] + %0 = tensor.expand_shape %arg0 [] : tensor into tensor<1xf32> + %1 = tensor.expand_shape %0 [[0, 1, 2]] : tensor<1xf32> into tensor<1x1x1xf32> return %1 : tensor<1x1x1xf32> } // CHECK-LABEL: compose_expand_of_expand_of_zero_dim -// CHECK: tensor.expand_shape %{{.*}} [] output_shape [1, 1, 1] +// CHECK: tensor.expand_shape %{{.*}} [] // CHECK-SAME: tensor into tensor<1x1x1xf32> // ----- @@ -1092,7 +1093,7 @@ func.func @collapse_of_cast(%t: tensor<8x12x32xf32>) -> tensor { // ----- func.func @fold_collapse_of_expand(%arg0 : tensor<12x4xf32>) -> tensor<12x4xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [3, 4, 4] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] : tensor<12x4xf32> into tensor<3x4x4xf32> %1 = tensor.collapse_shape %0 [[0, 1], [2]] : tensor<3x4x4xf32> into tensor<12x4xf32> @@ -1103,9 +1104,9 @@ func.func @fold_collapse_of_expand(%arg0 : tensor<12x4xf32>) -> tensor<12x4xf32> // ----- -func.func @fold_collapse_of_expand_dynamic(%arg0 : tensor, %arg1: index, %arg2: index) +func.func @fold_collapse_of_expand_dynamic(%arg0 : tensor) -> tensor { - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [%arg1, 4, %arg2] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] : tensor into tensor %1 = tensor.collapse_shape %0 [[0, 1], [2]] : tensor into tensor @@ -1120,7 +1121,7 @@ func.func @compose_expand_of_collapse(%arg0 : tensor<2x3x4x5x6x7x8xf32>) -> tensor<24x5x42x8xf32> { %0 = tensor.collapse_shape %arg0 [[0, 1, 2, 3, 4, 5, 6]] : tensor<2x3x4x5x6x7x8xf32> into tensor<40320xf32> - %1 = tensor.expand_shape %0 [[0, 1, 2, 3]] output_shape [24, 5, 42, 8] + %1 = tensor.expand_shape %0 [[0, 1, 2, 3]] : tensor<40320xf32> into tensor<24x5x42x8xf32> return %1 : tensor<24x5x42x8xf32> } @@ -1136,7 +1137,7 @@ func.func @compose_expand_of_collapse_7D(%arg0 : tensor<24x5x42x8xf32>) -> tensor<2x3x4x5x6x7x8xf32> { %0 = tensor.collapse_shape %arg0 [[0, 1, 2, 3]] : tensor<24x5x42x8xf32> into tensor<40320xf32> - %1 = tensor.expand_shape %0 [[0, 1, 2, 3, 4, 5, 6]] output_shape [2, 3, 4, 5, 6, 7, 8] + %1 = tensor.expand_shape %0 [[0, 1, 2, 3, 4, 5, 6]] : tensor<40320xf32> into tensor<2x3x4x5x6x7x8xf32> return %1 : tensor<2x3x4x5x6x7x8xf32> } @@ -1148,16 +1149,16 @@ func.func @compose_expand_of_collapse_7D(%arg0 : tensor<24x5x42x8xf32>) // ----- -func.func @compose_collapse_of_expand(%arg : tensor, %arg1: index, %arg2: index, %arg3: index) +func.func @compose_collapse_of_expand(%arg : tensor) -> tensor { - %0 = tensor.expand_shape %arg [[0], [1], [2, 3]] output_shape [%arg1, %arg2, %arg3, 1] + %0 = tensor.expand_shape %arg [[0], [1], [2, 3]] : tensor into tensor %1 = tensor.collapse_shape %0 [[0, 1], [2, 3]] : tensor into tensor return %1 : tensor } // CHECK-LABEL: func @compose_collapse_of_expand -// CHECK: (%[[ARG:.*]]: tensor, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index) +// CHECK: (%[[ARG:.*]]: tensor) // CHECK-NEXT: tensor.collapse_shape %[[ARG]] // CHECK-SAME: [0, 1], [2] // CHECK-SAME: : tensor into tensor @@ -1166,14 +1167,14 @@ func.func @compose_collapse_of_expand(%arg : tensor, %arg1: index, %a func.func @compose_collapse_of_expand_1D(%arg0 : tensor<2048xf32>) -> tensor<4x512xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3]] output_shape [1, 4, 1, 512] + %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3]] : tensor<2048xf32> into tensor<1x4x1x512xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3]] : tensor<1x4x1x512xf32> into tensor<4x512xf32> return %1 : tensor<4x512xf32> } // CHECK: func @compose_collapse_of_expand_1D -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] output_shape [4, 512] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] // CHECK-SAME: tensor<2048xf32> into tensor<4x512xf32> // ----- @@ -1182,14 +1183,14 @@ func.func @compose_expand_of_collapse_0_rank_to_expand(%arg0 : tensor<1x1x1xf32> -> tensor<1x1x1x1xf32> { %0 = tensor.collapse_shape %arg0 [] : tensor<1x1x1xf32> into tensor - %1 = tensor.expand_shape %0 [] output_shape [1, 1, 1, 1] + %1 = tensor.expand_shape %0 [] : tensor into tensor<1x1x1x1xf32> return %1 : tensor<1x1x1x1xf32> } // CHECK: func @compose_expand_of_collapse_0_rank_to_expand // CHECK-SAME: %[[ARG0:.+]]: tensor<1x1x1xf32> // CHECK: %[[RESULT:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: {{\[}}[0], [1], [2, 3]] output_shape [1, 1, 1, 1] +// CHECK-SAME: [0], [1], [2, 3] // CHECK: return %[[RESULT]] // ----- @@ -1198,7 +1199,7 @@ func.func @compose_expand_of_collapse_0_rank_to_collapse(%arg0 : tensor<1x1x1x1x -> tensor<1x1x1xf32> { %0 = tensor.collapse_shape %arg0 [] : tensor<1x1x1x1xf32> into tensor - %1 = tensor.expand_shape %0 [] output_shape [1, 1, 1] + %1 = tensor.expand_shape %0 [] : tensor into tensor<1x1x1xf32> return %1 : tensor<1x1x1xf32> } @@ -1213,8 +1214,8 @@ func.func @compose_expand_of_collapse_0_rank_to_collapse(%arg0 : tensor<1x1x1x1x // CHECK-LABEL: func @zero_rank_reshape_multi func.func @zero_rank_reshape_multi(%arg0: tensor) -> tensor { // CHECK: return %arg0 - %0 = tensor.expand_shape %arg0 [] output_shape [1] : tensor into tensor<1xf32> - %1 = tensor.expand_shape %0 [[0, 1]] output_shape [1, 1] : tensor<1xf32> into tensor<1x1xf32> + %0 = tensor.expand_shape %arg0 [] : tensor into tensor<1xf32> + %1 = tensor.expand_shape %0 [[0, 1]] : tensor<1xf32> into tensor<1x1xf32> %2 = tensor.collapse_shape %1 [] : tensor<1x1xf32> into tensor return %2 : tensor } @@ -1249,7 +1250,7 @@ func.func @compose_collapse_of_collapse_zero_dim(%arg0 : tensor<1x1x1xf32>) // ----- func.func @fold_collapse_of_expand_1D(%arg0 : tensor<4x512xf32>) -> tensor<2048xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2], [3]] output_shape [1, 4, 1, 512] + %0 = tensor.expand_shape %arg0 [[0, 1, 2], [3]] : tensor<4x512xf32> into tensor<1x4x1x512xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2, 3]] : tensor<1x4x1x512xf32> into tensor<2048xf32> @@ -1263,40 +1264,42 @@ func.func @fold_collapse_of_expand_1D(%arg0 : tensor<4x512xf32>) -> tensor<2048x func.func @fold_collapse_of_expand_unit_dims(%arg0 : tensor<2048x1x1xf32>) -> tensor<4x512x1x1xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3], [4], [5]] output_shape [1, 4, 1, 512, 1, 1] : tensor<2048x1x1xf32> into tensor<1x4x1x512x1x1xf32> + %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3], [4], [5]] + : tensor<2048x1x1xf32> into tensor<1x4x1x512x1x1xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3], [4], [5]] : tensor<1x4x1x512x1x1xf32> into tensor<4x512x1x1xf32> return %1 : tensor<4x512x1x1xf32> } // CHECK: func @fold_collapse_of_expand_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3]] output_shape [4, 512, 1, 1] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3]] // CHECK-SAME: tensor<2048x1x1xf32> into tensor<4x512x1x1xf32> // ----- func.func @compose_collapse_of_expand_unit_dims(%arg0 : tensor<2048x1x2048xf32>) -> tensor<4x512x1x512x4xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3, 4], [5], [6, 7, 8]] output_shape [1, 4, 1, 512, 1, 1, 512, 1, 4] : tensor<2048x1x2048xf32> into tensor<1x4x1x512x1x1x512x1x4xf32> + %0 = tensor.expand_shape %arg0 [[0, 1, 2, 3, 4], [5], [6, 7, 8]] + : tensor<2048x1x2048xf32> into tensor<1x4x1x512x1x1x512x1x4xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3, 4], [5], [6, 7], [8]] : tensor<1x4x1x512x1x1x512x1x4xf32> into tensor<4x512x1x512x4xf32> return %1 : tensor<4x512x1x512x4xf32> } // CHECK: func @compose_collapse_of_expand_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3, 4]] output_shape [4, 512, 1, 512, 4] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1], [2], [3, 4]] // CHECK-SAME: tensor<2048x1x2048xf32> into tensor<4x512x1x512x4xf32> // ----- func.func @compose_collapse_of_expand_trailing_unit_dims(%arg0: tensor<2xf32>) -> tensor<2x1xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2]] output_shape [2, 1, 1] + %0 = tensor.expand_shape %arg0 [[0, 1, 2]] : tensor<2xf32> into tensor<2x1x1xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2]] : tensor<2x1x1xf32> into tensor<2x1xf32> return %1 : tensor<2x1xf32> } // CHECK: func @compose_collapse_of_expand_trailing_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] output_shape [2, 1] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] // CHECK-SAME: tensor<2xf32> into tensor<2x1xf32> // ----- @@ -1318,13 +1321,14 @@ func.func @compose_collapse_of_collapse_unit_dims_dynamic( func.func @fold_collapse_of_expand_trailing_unit_dims(%arg0: tensor<2xf32>) -> tensor<2x1xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1, 2]] output_shape [2, 1, 1] : tensor<2xf32> into tensor<2x1x1xf32> + %0 = tensor.expand_shape %arg0 [[0, 1, 2]] + : tensor<2xf32> into tensor<2x1x1xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2]] : tensor<2x1x1xf32> into tensor<2x1xf32> return %1 : tensor<2x1xf32> } // CHECK: func @fold_collapse_of_expand_trailing_unit_dims -// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] output_shape [2, 1] +// CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1]] // CHECK-SAME: tensor<2xf32> into tensor<2x1xf32> // ----- @@ -1345,7 +1349,8 @@ func.func @fold_collapse_of_collapse_trailing_unit_dims_dynamic( func.func @fold_collapse_of_expand_trailing_unit_dims(%arg0: tensor<12x42x1x1xf32>) -> tensor<12x42xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1], [2], [3, 4]] output_shape [12, 42, 1, 1, 1] : tensor<12x42x1x1xf32> into tensor<12x42x1x1x1xf32> + %0 = tensor.expand_shape %arg0 [[0], [1], [2], [3, 4]] + : tensor<12x42x1x1xf32> into tensor<12x42x1x1x1xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2, 3, 4]] : tensor<12x42x1x1x1xf32> into tensor<12x42xf32> return %1 : tensor<12x42xf32> @@ -1356,9 +1361,9 @@ func.func @fold_collapse_of_expand_trailing_unit_dims(%arg0: tensor<12x42x1x1xf3 // ----- -func.func @fold_collapse_of_expand_unit_dims_in_middle(%arg0 : tensor, %sz0: index, %sz1: index, %sz2: index) +func.func @fold_collapse_of_expand_unit_dims_in_middle(%arg0 : tensor) -> tensor { - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] output_shape [%sz0, %sz1, 1, %sz2] + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] : tensor into tensor %1 = tensor.collapse_shape %0 [[0], [1, 2, 3]] : tensor into tensor @@ -1373,7 +1378,7 @@ func.func @fold_collapse_of_expand_unit_dims_in_middle(%arg0 : tensor func.func @no_fold_collapse_of_expand_incompatible(%arg0 : tensor<4x6x8xf32>) -> tensor<2x6x16xf32> { - %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3], [4]] output_shape [2, 2, 3, 2, 8] + %0 = tensor.expand_shape %arg0 [[0, 1], [2, 3], [4]] : tensor<4x6x8xf32> into tensor<2x2x3x2x8xf32> %1 = tensor.collapse_shape %0 [[0], [1, 2], [3, 4]] : tensor<2x2x3x2x8xf32> into tensor<2x6x16xf32> @@ -1387,7 +1392,7 @@ func.func @no_fold_collapse_of_expand_incompatible(%arg0 : tensor<4x6x8xf32>) func.func @no_fold_collapse_of_expand_empty_expr(%arg0: tensor<3x2x2xf32>) -> tensor<12x1xf32> { - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] output_shape [3, 2, 2, 1] + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3]] : tensor<3x2x2xf32> into tensor<3x2x2x1xf32> %1 = tensor.collapse_shape %0 [[0, 1, 2], [3]] : tensor<3x2x2x1xf32> into tensor<12x1xf32> @@ -1396,7 +1401,7 @@ func.func @no_fold_collapse_of_expand_empty_expr(%arg0: tensor<3x2x2xf32>) // CHECK: func @no_fold_collapse_of_expand_empty_expr // CHECK-SAME: %[[ARG0:.+]]: tensor<3x2x2xf32> // CHECK: %[[RARG0:.+]] = tensor.expand_shape %[[ARG0]] -// CHECK-SAME: {{\[}}[0], [1], [2, 3]] output_shape [3, 2, 2, 1] +// CHECK-SAME: [0], [1], [2, 3] // CHECK: %[[RES:.+]] = tensor.collapse_shape %[[RARG0]] // CHECK-SAME: [0, 1, 2], [3] // CHECK: return %[[RES:.+]] : tensor<12x1xf32> @@ -1405,7 +1410,7 @@ func.func @no_fold_collapse_of_expand_empty_expr(%arg0: tensor<3x2x2xf32>) func.func @reshape_splat_constant_int32() -> tensor<2x4x2xi32> { %c0 = arith.constant dense<42> : tensor<2x8xi32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x8xi32> into tensor<2x4x2xi32> return %0 : tensor<2x4x2xi32> } @@ -1416,7 +1421,7 @@ func.func @reshape_splat_constant_int32() -> tensor<2x4x2xi32> { // ----- func.func @expand_shape_splat(%arg : f32) -> tensor<2x2x2xf32> { %c0 = tensor.splat %arg : tensor<2x4xf32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 2, 2] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x4xf32> into tensor<2x2x2xf32> return %0 : tensor<2x2x2xf32> } @@ -1429,12 +1434,13 @@ func.func @expand_shape_splat(%arg : f32) -> tensor<2x2x2xf32> { // ----- // CHECK-LABEL: @expand_shape_splat_dynamic_no_fold -// CHECK-SAME: (%[[F:.+]]: f32, %[[M:.+]]: index, %[[SZ0:.+]]: index) -func.func @expand_shape_splat_dynamic_no_fold(%arg: f32, %m: index, %sz0: index) -> tensor<2x2x?xf32> { - // CHECK: %[[SPLAT:.+]] = tensor.splat %[[F]][%[[M]]] : tensor<2x?xf32> +// CHECK-SAME: %[[F:.+]]: f32 +// CHECK-SAME: %[[M:.+]]: index +func.func @expand_shape_splat_dynamic_no_fold(%arg: f32, %m: index) -> tensor<2x2x?xf32> { + // CHECK: %[[SPLAT:.+]] = tensor.splat %[[F]][%[[M]]] // CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[SPLAT]] %c0 = tensor.splat %arg[%m] : tensor<2x?xf32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 2, %sz0] : tensor<2x?xf32> into tensor<2x2x?xf32> + %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x?xf32> into tensor<2x2x?xf32> return %0 : tensor<2x2x?xf32> } @@ -1469,7 +1475,7 @@ func.func @collapse_shape_splat_dynamic_no_fold(%f: f32, %m: index) -> tensor<2x func.func @reshape_splat_constant_int16() -> tensor<2x4x2xi16> { %c0 = arith.constant dense<42> : tensor<2x8xi16> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x8xi16> into tensor<2x4x2xi16> return %0 : tensor<2x4x2xi16> } @@ -1482,7 +1488,7 @@ func.func @reshape_splat_constant_int16() -> tensor<2x4x2xi16> { func.func @reshape_splat_constant_float32() -> tensor<2x4x2xf32> { %c0 = arith.constant dense<42.0> : tensor<2x8xf32> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x8xf32> into tensor<2x4x2xf32> return %0 : tensor<2x4x2xf32> } @@ -1495,7 +1501,7 @@ func.func @reshape_splat_constant_float32() -> tensor<2x4x2xf32> { func.func @reshape_splat_constant_float64() -> tensor<2x4x2xf64> { %c0 = arith.constant dense<42.0> : tensor<2x8xf64> - %0 = tensor.expand_shape %c0 [[0], [1, 2]] output_shape [2, 4, 2] + %0 = tensor.expand_shape %c0 [[0], [1, 2]] : tensor<2x8xf64> into tensor<2x4x2xf64> return %0 : tensor<2x4x2xf64> } @@ -1845,7 +1851,7 @@ func.func @fold_expand_shape_from_elements(%arg0: i32) -> tensor<1xi32> { // CHECK: %[[FROM:.+]] = tensor.from_elements %arg0 : tensor<1xi32> // CHECK: return %[[FROM]] : tensor<1xi32> %0 = tensor.from_elements %arg0 : tensor - %1 = tensor.expand_shape %0 [] output_shape [1] : tensor into tensor<1xi32> + %1 = tensor.expand_shape %0 [] : tensor into tensor<1xi32> return %1 : tensor<1xi32> } @@ -2067,9 +2073,9 @@ func.func @empty_tensor_canonicalize(%i : index) { // CHECK: %[[dim:.*]] = tensor.dim %[[t]], %[[c1]] : tensor // CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%[[dim]]] // CHECK: return %[[apply]] -func.func @dim_of_expand_shape(%t: tensor, %sz0: index, %sz1: index) -> index { +func.func @dim_of_expand_shape(%t: tensor) -> index { %c2 = arith.constant 2 : index - %0 = tensor.expand_shape %t [[0], [1, 2, 3, 4, 5]] output_shape [%sz0, 1, %sz1, 5, 1, 8] + %0 = tensor.expand_shape %t [[0], [1, 2, 3, 4, 5]] : tensor into tensor %1 = tensor.dim %0, %c2 : tensor return %1 : index @@ -2101,9 +2107,9 @@ func.func @dim_of_collapse_shape(%t: tensor) -> index { // CHECK-LABEL: func @collapse_expand_fold_to_cast( // CHECK-SAME: %[[t:.*]]: tensor // CHECK: return %[[t]] -func.func @collapse_expand_fold_to_cast(%t: tensor, %sz0: index) -> (tensor) +func.func @collapse_expand_fold_to_cast(%t: tensor) -> (tensor) { - %0 = tensor.expand_shape %t [[0, 1]] output_shape [1, %sz0] : tensor into tensor<1x?xf32> + %0 = tensor.expand_shape %t [[0, 1]] : tensor into tensor<1x?xf32> %1 = tensor.collapse_shape %0 [[0, 1]] : tensor<1x?xf32> into tensor return %1 : tensor } diff --git a/mlir/test/Dialect/Tensor/fold-empty-op.mlir b/mlir/test/Dialect/Tensor/fold-empty-op.mlir index e200a4f89261..15f841f2128e 100644 --- a/mlir/test/Dialect/Tensor/fold-empty-op.mlir +++ b/mlir/test/Dialect/Tensor/fold-empty-op.mlir @@ -13,9 +13,10 @@ module attributes {transform.with_named_sequence} { // CHECK: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 floordiv 28)> // CHECK: #[[$MAP2:.+]] = affine_map<()[s0] -> (s0 * 28)> -func.func @empty_reshape_expansion(%arg0 : index, %sz0: index) -> tensor<2x3x5x4x?x7xf32> { +func.func @empty_reshape_expansion(%arg0 : index) -> tensor<2x3x5x4x?x7xf32> { %0 = tensor.empty(%arg0) : tensor<6x5x?xf32> - %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4, 5]] output_shape [2, 3, 5, 4, %sz0, 7] : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> + %1 = tensor.expand_shape %0 [[0, 1], [2], [3, 4, 5]] + : tensor<6x5x?xf32> into tensor<2x3x5x4x?x7xf32> return %1 : tensor<2x3x5x4x?x7xf32> } // CHECK-LABEL: func @empty_reshape_expansion diff --git a/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir b/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir index d3ac6ce792f3..625408dfefe2 100644 --- a/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir +++ b/mlir/test/Dialect/Tensor/fold-reassociative-reshapes.mlir @@ -11,11 +11,9 @@ func.func @expand_shape_of_rank_reducing_extract( { %0 = tensor.extract_slice %t[0, 0, 0, 0][%idx, 1, 1, 5][1, 1, 1, 1] : tensor to tensor - %c0 = arith.constant 0 : index - %sz0 = tensor.dim %0, %c0 : tensor - %1 = tensor.expand_shape %0 [[0], [1, 2], [3]] output_shape [%sz0, 1, 1, 5] + %1 = tensor.expand_shape %0 [[0], [1, 2], [3]] : tensor into tensor - %2 = tensor.expand_shape %0 [[0, 1], [2], [3]] output_shape [%sz0, 1, 1, 5] + %2 = tensor.expand_shape %0 [[0, 1], [2], [3]] : tensor into tensor return %1, %2 : tensor, tensor } diff --git a/mlir/test/Dialect/Tensor/invalid.mlir b/mlir/test/Dialect/Tensor/invalid.mlir index 3617ed5d61af..79ca0de68a1e 100644 --- a/mlir/test/Dialect/Tensor/invalid.mlir +++ b/mlir/test/Dialect/Tensor/invalid.mlir @@ -273,10 +273,21 @@ func.func @insert_slice_wrong_dynamic_type(%t1: tensor, %t2: tensor<8 // ----- +func.func @illegal_expanding_reshape_dynamic_tensor + (%arg0: tensor) -> tensor { + // expected-error @+1 {{invalid to have a single dimension (2) expanded into multiple dynamic dims (2,4)}} + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3, 4]] + : tensor into tensor + return %0 : tensor +} + +// ----- + + func.func @illegal_expanding_reshape_static_tensor (%arg0: tensor<2x3x20xf32>) -> tensor<2x3x2x4x5xf32> { // expected-error @+1 {{expected dimension 2 of collapsed type to be static value of 40}} - %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3, 4]] output_shape [2, 3, 2, 4, 5] + %0 = tensor.expand_shape %arg0 [[0], [1], [2, 3, 4]] : tensor<2x3x20xf32> into tensor<2x3x2x4x5xf32> return %0 : tensor<2x3x2x4x5xf32> } @@ -293,20 +304,20 @@ func.func @illegal_collapsing_reshape_static_tensor // ----- -func.func @illegal_expanding_reshape_mixed_tensor(%arg0 : tensor, %sz0: index) +func.func @illegal_expanding_reshape_mixed_tensor(%arg0 : tensor) -> tensor { // expected-error @+1 {{expected dimension 1 of collapsed type to be static value of 5}} - %0 = tensor.expand_shape %arg0 [[0, 1], [2]] output_shape [%sz0, 4, 5] + %0 = tensor.expand_shape %arg0 [[0, 1], [2]] : tensor into tensor return %0 : tensor } // ----- -func.func @illegal_expanding_reshape_mixed_tensor_2(%arg0 : tensor, %sz0: index) +func.func @illegal_expanding_reshape_mixed_tensor_2(%arg0 : tensor) -> tensor { // expected-error @+1 {{expected dimension 1 of collapsed type to be static value of 20}} - %0 = tensor.expand_shape %arg0 [[0], [1, 2]] output_shape [%sz0, 4, 5] + %0 = tensor.expand_shape %arg0 [[0], [1, 2]] : tensor into tensor return %0 : tensor } diff --git a/mlir/test/Dialect/Tensor/ops.mlir b/mlir/test/Dialect/Tensor/ops.mlir index 378137a14b59..2b0a74acce08 100644 --- a/mlir/test/Dialect/Tensor/ops.mlir +++ b/mlir/test/Dialect/Tensor/ops.mlir @@ -194,26 +194,12 @@ func.func @insert_slice( func.func @tensor_reshape_zero_dim(%arg0 : tensor<1x1xf32>, %arg1 : tensor) -> (tensor, tensor<1x1xf32>) { %0 = tensor.collapse_shape %arg0 [] : tensor<1x1xf32> into tensor - %1 = tensor.expand_shape %0 [] output_shape [1, 1] : tensor into tensor<1x1xf32> + %1 = tensor.expand_shape %0 [] : tensor into tensor<1x1xf32> return %0, %1 : tensor, tensor<1x1xf32> } // CHECK-LABEL: func @tensor_reshape_zero_dim // CHECK: tensor.collapse_shape %{{.*}} [] : tensor<1x1xf32> into tensor -// CHECK: tensor.expand_shape %{{.*}} [] output_shape [1, 1] : tensor into tensor<1x1xf32> - -// ----- - -func.func @tensor_expand_shape_dynamic_dim(%arg0 : tensor, %sz0 : index, %sz1 : index, %sz2 : index) - -> (tensor<5x?x?x?xf32>) { - %1 = tensor.expand_shape %arg0 [[0, 1], [2, 3]] output_shape [5, %sz0, %sz1, %sz2] : tensor into tensor<5x?x?x?xf32> - return %1 : tensor<5x?x?x?xf32> -} - -// CHECK-LABEL: func.func @tensor_expand_shape_dynamic_dim(%arg0: tensor, %arg1: index, %arg2: index, %arg3: index) -> tensor<5x?x?x?xf32> { -// CHECK: %expanded = tensor.expand_shape %arg0 {{\[\[}}0, 1], [2, 3{{\]\]}} output_shape [5, %arg1, %arg2, %arg3] : tensor into tensor<5x?x?x?xf32> -// CHECK: return %expanded : tensor<5x?x?x?xf32> -// CHECK: } - +// CHECK: tensor.expand_shape %{{.*}} [] : tensor into tensor<1x1xf32> // ----- diff --git a/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir b/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir index 5a2eade0eccc..9948c0246e6e 100644 --- a/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir +++ b/mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir @@ -2,7 +2,7 @@ // CHECK-LABEL: func.func @single_dim_packing( // CHECK-SAME: %[[ARG0:.+]]: tensor<256xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] output_shape [8, 32] : tensor<256xf32> into tensor<8x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] : tensor<256xf32> into tensor<8x32xf32> // CHECK: return %[[EXPANDED]] : tensor<8x32xf32> func.func @single_dim_packing(%arg0: tensor<256xf32>) -> tensor<8x32xf32> { %empty = tensor.empty() : tensor<8x32xf32> @@ -27,7 +27,7 @@ func.func @single_dim_packing_with_padding(%arg0: tensor<255xf32>) -> tensor<8x3 // CHECK-LABEL: func.func @single_last_inner_dim_packing( // CHECK-SAME: %[[ARG0:.+]]: tensor<5x256xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] output_shape [5, 8, 32] : tensor<5x256xf32> into tensor<5x8x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<5x256xf32> into tensor<5x8x32xf32> // CHECK: return %[[EXPANDED]] : tensor<5x8x32xf32> func.func @single_last_inner_dim_packing(%arg0: tensor<5x256xf32>) -> tensor<5x8x32xf32> { %empty = tensor.empty() : tensor<5x8x32xf32> @@ -39,7 +39,7 @@ func.func @single_last_inner_dim_packing(%arg0: tensor<5x256xf32>) -> tensor<5x8 // CHECK-LABEL: func.func @pack_1d_with_outer_dims_perm( // CHECK-SAME: %[[ARG0:.+]]: tensor<64xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] output_shape [2, 32] : tensor<64xf32> into tensor<2x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] : tensor<64xf32> into tensor<2x32xf32> // CHECK: return %[[EXPANDED]] : tensor<2x32xf32> func.func @pack_1d_with_outer_dims_perm(%arg0: tensor<64xf32>) -> tensor<2x32xf32> { %empty = tensor.empty() : tensor<2x32xf32> @@ -51,7 +51,7 @@ func.func @pack_1d_with_outer_dims_perm(%arg0: tensor<64xf32>) -> tensor<2x32xf3 // CHECK-LABEL: func.func @single_last_inner_dim_packing_with_identity_outer_dims_perm( // CHECK-SAME: %[[ARG0:.+]]: tensor<5x256xf32>) -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] output_shape [5, 8, 32] : tensor<5x256xf32> into tensor<5x8x32xf32> +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<5x256xf32> into tensor<5x8x32xf32> // CHECK: return %[[EXPANDED]] : tensor<5x8x32xf32> func.func @single_last_inner_dim_packing_with_identity_outer_dims_perm(%arg0: tensor<5x256xf32>) -> tensor<5x8x32xf32> { %empty = tensor.empty() : tensor<5x8x32xf32> @@ -85,7 +85,7 @@ func.func @single_first_inner_dim_packing(%arg0: tensor<256x5xf32>) -> tensor<8x // CHECK-LABEL: func.func @pack_1x32_to_1x32x1x1 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] output_shape [1, 32, 1, 1] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] // CHECK: return %[[EXPANDED]] func.func @pack_1x32_to_1x32x1x1(%arg0 : tensor<1x32xf32>) -> tensor<1x32x1x1xf32> { %empty = tensor.empty() : tensor<1x32x1x1xf32> @@ -98,7 +98,7 @@ func.func @pack_1x32_to_1x32x1x1(%arg0 : tensor<1x32xf32>) -> tensor<1x32x1x1xf3 // CHECK-LABEL: func.func @pack_1x32_to_1x16x1x2 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] output_shape [1, 16, 1, 2] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2, 3]] // CHECK: return %[[EXPANDED]] func.func @pack_1x32_to_1x16x1x2(%arg0 : tensor<1x32xf32>) -> tensor<1x16x1x2xf32> { %empty = tensor.empty() : tensor<1x16x1x2xf32> @@ -111,7 +111,7 @@ func.func @pack_1x32_to_1x16x1x2(%arg0 : tensor<1x32xf32>) -> tensor<1x16x1x2xf3 // CHECK-LABEL: func.func @pack_32x1_to_16x1x2x1 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]] -// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] output_shape [1, 16, 2, 1] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3]] // CHECK: return %[[EXPANDED]] func.func @pack_32x1_to_16x1x2x1(%arg0 : tensor<32x1xf32>) -> tensor<1x16x2x1xf32> { %empty = tensor.empty() : tensor<1x16x2x1xf32> diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 8c6752edc28d..6c732b8f1349 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -3831,7 +3831,6 @@ cc_library( includes = ["include"], deps = [ ":DialectUtilsIncGen", - ":ArithDialect", ":IR", ":Support", "//llvm:Support", -- GitLab From 18bb175428f520aaa4a5e388bd3b680a1a7c60c0 Mon Sep 17 00:00:00 2001 From: David Green Date: Sun, 21 Apr 2024 13:53:22 +0100 Subject: [PATCH 107/357] [AArch64] Add costs for LD3/LD4 shuffles. Similar to #87934, this adds costs to the shuffles in a canonical LD3/LD4 pattern, which are represented in LLVM as deinterleaving-shuffle(load). This likely has less effect at the moment than the ST3/ST4 costs as instcombine will perform certain transforms without considering the cost. --- .../llvm/Analysis/TargetTransformInfoImpl.h | 4 +- llvm/include/llvm/IR/Instructions.h | 10 + llvm/lib/CodeGen/InterleavedAccessPass.cpp | 32 +-- llvm/lib/IR/Instructions.cpp | 25 ++ .../AArch64/AArch64TargetTransformInfo.cpp | 11 +- .../CostModel/AArch64/shuffle-load.ll | 232 +++++++++--------- 6 files changed, 168 insertions(+), 146 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 5b40e4971406..4d5cd963e092 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1376,7 +1376,7 @@ public: return TargetTTI->getShuffleCost( IsUnary ? TTI::SK_PermuteSingleSrc : TTI::SK_PermuteTwoSrc, VecTy, - AdjustMask, CostKind, 0, nullptr, {}, Shuffle); + AdjustMask, CostKind, 0, nullptr, Operands, Shuffle); } // Narrowing shuffle - perform shuffle at original wider width and @@ -1385,7 +1385,7 @@ public: InstructionCost ShuffleCost = TargetTTI->getShuffleCost( IsUnary ? TTI::SK_PermuteSingleSrc : TTI::SK_PermuteTwoSrc, - VecSrcTy, AdjustMask, CostKind, 0, nullptr, {}, Shuffle); + VecSrcTy, AdjustMask, CostKind, 0, nullptr, Operands, Shuffle); SmallVector ExtractMask(Mask.size()); std::iota(ExtractMask.begin(), ExtractMask.end(), 0); diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index 4ffa6349871b..d7ec3c16bec2 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -2631,6 +2631,16 @@ public: return isInterleaveMask(Mask, Factor, NumInputElts, StartIndexes); } + /// Check if the mask is a DE-interleave mask of the given factor + /// \p Factor like: + /// + static bool isDeInterleaveMaskOfFactor(ArrayRef Mask, unsigned Factor, + unsigned &Index); + static bool isDeInterleaveMaskOfFactor(ArrayRef Mask, unsigned Factor) { + unsigned Unused; + return isDeInterleaveMaskOfFactor(Mask, Factor, Unused); + } + /// Checks if the shuffle is a bit rotation of the first operand across /// multiple subelements, e.g: /// diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp index 438ac1c3cc6e..8989eabbe6df 100644 --- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp +++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp @@ -200,28 +200,6 @@ FunctionPass *llvm::createInterleavedAccessPass() { return new InterleavedAccess(); } -/// Check if the mask is a DE-interleave mask of the given factor -/// \p Factor like: -/// -static bool isDeInterleaveMaskOfFactor(ArrayRef Mask, unsigned Factor, - unsigned &Index) { - // Check all potential start indices from 0 to (Factor - 1). - for (Index = 0; Index < Factor; Index++) { - unsigned i = 0; - - // Check that elements are in ascending order by Factor. Ignore undef - // elements. - for (; i < Mask.size(); i++) - if (Mask[i] >= 0 && static_cast(Mask[i]) != Index + i * Factor) - break; - - if (i == Mask.size()) - return true; - } - - return false; -} - /// Check if the mask is a DE-interleave mask for an interleaved load. /// /// E.g. DE-interleave masks (Factor = 2) could be: @@ -238,7 +216,7 @@ static bool isDeInterleaveMask(ArrayRef Mask, unsigned &Factor, // Make sure we don't produce a load wider than the input load. if (Mask.size() * Factor > NumLoadElements) return false; - if (isDeInterleaveMaskOfFactor(Mask, Factor, Index)) + if (ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor, Index)) return true; } @@ -333,8 +311,8 @@ bool InterleavedAccessImpl::lowerInterleavedLoad( for (auto *Shuffle : Shuffles) { if (Shuffle->getType() != VecTy) return false; - if (!isDeInterleaveMaskOfFactor(Shuffle->getShuffleMask(), Factor, - Index)) + if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor( + Shuffle->getShuffleMask(), Factor, Index)) return false; assert(Shuffle->getShuffleMask().size() <= NumLoadElements); @@ -343,8 +321,8 @@ bool InterleavedAccessImpl::lowerInterleavedLoad( for (auto *Shuffle : BinOpShuffles) { if (Shuffle->getType() != VecTy) return false; - if (!isDeInterleaveMaskOfFactor(Shuffle->getShuffleMask(), Factor, - Index)) + if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor( + Shuffle->getShuffleMask(), Factor, Index)) return false; assert(Shuffle->getShuffleMask().size() <= NumLoadElements); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index cec02e2ce633..d2babc748731 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2978,6 +2978,31 @@ bool ShuffleVectorInst::isInterleaveMask( return true; } +/// Check if the mask is a DE-interleave mask of the given factor +/// \p Factor like: +/// +bool ShuffleVectorInst::isDeInterleaveMaskOfFactor(ArrayRef Mask, + unsigned Factor, + unsigned &Index) { + // Check all potential start indices from 0 to (Factor - 1). + for (unsigned Idx = 0; Idx < Factor; Idx++) { + unsigned I = 0; + + // Check that elements are in ascending order by Factor. Ignore undef + // elements. + for (; I < Mask.size(); I++) + if (Mask[I] >= 0 && static_cast(Mask[I]) != Idx + I * Factor) + break; + + if (I == Mask.size()) { + Index = Idx; + return true; + } + } + + return false; +} + /// Try to lower a vector shuffle as a bit rotation. /// /// Look for a repeated rotation pattern in each sub group. diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index e80931a03f30..700242b88346 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -3827,9 +3827,18 @@ InstructionCost AArch64TTIImpl::getShuffleCost( Tp->getScalarSizeInBits() == LT.second.getScalarSizeInBits() && Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) { + // Check for LD3/LD4 instructions, which are represented in llvm IR as + // deinterleaving-shuffle(load). The shuffle cost could potentially be free, + // but we model it with a cost of LT.first so that LD3/LD4 have a higher + // cost than just the load. + if (Args.size() >= 1 && isa(Args[0]) && + (ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, 3) || + ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, 4))) + return std::max(1, LT.first / 4); + // Check for ST3/ST4 instructions, which are represented in llvm IR as // store(interleaving-shuffle). The shuffle cost could potentially be free, - // but we model it with a cost of LT.first so that LD3/LD3 have a higher + // but we model it with a cost of LT.first so that ST3/ST4 have a higher // cost than just the store. if (CxtI && CxtI->hasOneUse() && isa(*CxtI->user_begin()) && (ShuffleVectorInst::isInterleaveMask( diff --git a/llvm/test/Analysis/CostModel/AArch64/shuffle-load.ll b/llvm/test/Analysis/CostModel/AArch64/shuffle-load.ll index 106f2f9edc2e..bf81d7aa5e68 100644 --- a/llvm/test/Analysis/CostModel/AArch64/shuffle-load.ll +++ b/llvm/test/Analysis/CostModel/AArch64/shuffle-load.ll @@ -572,45 +572,45 @@ define void @vld3(ptr %p) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_1 = shufflevector <12 x i8> %v4i8, <12 x i8> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_2 = shufflevector <12 x i8> %v4i8, <12 x i8> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8 = load <24 x i8>, ptr %p, align 32 -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_0 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_1 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_2 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_1 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_2 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8 = load <48 x i8>, ptr %p, align 64 -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_0 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8_1 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_2 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_0 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_1 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_2 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16 = load <6 x i16>, ptr %p, align 16 ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_0 = shufflevector <6 x i16> %v2i16, <6 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_1 = shufflevector <6 x i16> %v2i16, <6 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_2 = shufflevector <6 x i16> %v2i16, <6 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16 = load <12 x i16>, ptr %p, align 32 -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_0 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_1 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_2 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_0 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_1 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_2 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16 = load <24 x i16>, ptr %p, align 64 -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_0 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_1 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_2 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_0 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_1 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_2 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16 = load <48 x i16>, ptr %p, align 128 -; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_0 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i16_1 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_2 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_0 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_1 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_2 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32 = load <6 x i32>, ptr %p, align 32 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_0 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32_1 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_1 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_2 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i32 = load <12 x i32>, ptr %p, align 64 -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_0 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i32_1 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_2 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_0 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_1 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_2 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i32 = load <24 x i32>, ptr %p, align 128 -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_0 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i32_1 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_2 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_0 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_1 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_2 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i32 = load <48 x i32>, ptr %p, align 256 -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_0 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i32_1 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_2 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_0 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_1 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_2 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i64 = load <6 x i64>, ptr %p, align 64 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_0 = shufflevector <6 x i64> %v2i64, <6 x i64> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_1 = shufflevector <6 x i64> %v2i64, <6 x i64> undef, <2 x i32> @@ -639,45 +639,45 @@ define void @vld3(ptr %p) { ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_1 = shufflevector <12 x i8> %v4i8, <12 x i8> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_2 = shufflevector <12 x i8> %v4i8, <12 x i8> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8 = load <24 x i8>, ptr %p, align 32 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_0 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_1 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_2 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_1 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_2 = shufflevector <24 x i8> %v8i8, <24 x i8> undef, <8 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8 = load <48 x i8>, ptr %p, align 64 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_0 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8_1 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_2 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_0 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_1 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_2 = shufflevector <48 x i8> %v16i8, <48 x i8> undef, <16 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16 = load <6 x i16>, ptr %p, align 16 ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_0 = shufflevector <6 x i16> %v2i16, <6 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_1 = shufflevector <6 x i16> %v2i16, <6 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_2 = shufflevector <6 x i16> %v2i16, <6 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16 = load <12 x i16>, ptr %p, align 32 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_0 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_1 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_2 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_0 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_1 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_2 = shufflevector <12 x i16> %v4i16, <12 x i16> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16 = load <24 x i16>, ptr %p, align 64 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_0 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_1 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_2 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_0 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_1 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_2 = shufflevector <24 x i16> %v8i16, <24 x i16> undef, <8 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16 = load <48 x i16>, ptr %p, align 128 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_0 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i16_1 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_2 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_0 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_1 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_2 = shufflevector <48 x i16> %v16i16, <48 x i16> undef, <16 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32 = load <6 x i32>, ptr %p, align 32 ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_0 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32_1 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_1 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_2 = shufflevector <6 x i32> %v2i32, <6 x i32> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i32 = load <12 x i32>, ptr %p, align 64 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_0 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i32_1 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_2 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_0 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_1 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_2 = shufflevector <12 x i32> %v4i32, <12 x i32> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i32 = load <24 x i32>, ptr %p, align 128 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_0 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i32_1 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_2 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_0 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_1 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_2 = shufflevector <24 x i32> %v8i32, <24 x i32> undef, <8 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i32 = load <48 x i32>, ptr %p, align 256 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_0 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i32_1 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_2 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_0 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_1 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_2 = shufflevector <48 x i32> %v16i32, <48 x i32> undef, <16 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i64 = load <6 x i64>, ptr %p, align 64 ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_0 = shufflevector <6 x i64> %v2i64, <6 x i64> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_1 = shufflevector <6 x i64> %v2i64, <6 x i64> undef, <2 x i32> @@ -780,55 +780,55 @@ define void @vld4(ptr %p) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_2 = shufflevector <16 x i8> %v4i8, <16 x i8> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_3 = shufflevector <16 x i8> %v4i8, <16 x i8> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8 = load <32 x i8>, ptr %p, align 32 -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_0 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_1 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_2 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_3 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_1 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_2 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_3 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8 = load <64 x i8>, ptr %p, align 64 -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_0 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_1 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_2 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_3 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_0 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_1 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_2 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_3 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16 = load <8 x i16>, ptr %p, align 16 ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_0 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_1 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_2 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_3 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16 = load <16 x i16>, ptr %p, align 32 -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_0 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_1 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_2 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_3 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_0 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_1 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_2 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_3 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16 = load <32 x i16>, ptr %p, align 64 -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_0 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_1 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_2 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_3 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_0 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_1 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_2 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_3 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16 = load <64 x i16>, ptr %p, align 128 -; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_0 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_1 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_2 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_3 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_0 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_1 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_2 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_3 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32 = load <8 x i32>, ptr %p, align 32 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_0 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_1 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_2 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32_3 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_3 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i32 = load <16 x i32>, ptr %p, align 64 -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_0 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_1 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_2 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_3 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_0 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_1 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_2 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_3 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i32 = load <32 x i32>, ptr %p, align 128 -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_0 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_1 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_2 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_3 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_0 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_1 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_2 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_3 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i32 = load <64 x i32>, ptr %p, align 256 -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_0 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_1 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_2 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_3 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_0 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_1 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_2 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_3 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i64 = load <8 x i64>, ptr %p, align 64 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_0 = shufflevector <8 x i64> %v2i64, <8 x i64> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_1 = shufflevector <8 x i64> %v2i64, <8 x i64> undef, <2 x i32> @@ -863,55 +863,55 @@ define void @vld4(ptr %p) { ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_2 = shufflevector <16 x i8> %v4i8, <16 x i8> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_3 = shufflevector <16 x i8> %v4i8, <16 x i8> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8 = load <32 x i8>, ptr %p, align 32 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_0 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_1 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_2 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 60 for instruction: %v8i8_3 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_1 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_2 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_3 = shufflevector <32 x i8> %v8i8, <32 x i8> undef, <8 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8 = load <64 x i8>, ptr %p, align 64 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_0 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_1 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_2 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i8_3 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_0 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_1 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_2 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_3 = shufflevector <64 x i8> %v16i8, <64 x i8> undef, <16 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16 = load <8 x i16>, ptr %p, align 16 ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_0 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_1 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_2 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i16_3 = shufflevector <8 x i16> %v2i16, <8 x i16> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16 = load <16 x i16>, ptr %p, align 32 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_0 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_1 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_2 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v4i16_3 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_0 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_1 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_2 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_3 = shufflevector <16 x i16> %v4i16, <16 x i16> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16 = load <32 x i16>, ptr %p, align 64 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_0 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_1 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_2 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16_3 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_0 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_1 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_2 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_3 = shufflevector <32 x i16> %v8i16, <32 x i16> undef, <8 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16 = load <64 x i16>, ptr %p, align 128 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_0 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_1 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_2 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v16i16_3 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_0 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_1 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_2 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i16_3 = shufflevector <64 x i16> %v16i16, <64 x i16> undef, <16 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32 = load <8 x i32>, ptr %p, align 32 ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_0 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_1 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_2 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i32_3 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_3 = shufflevector <8 x i32> %v2i32, <8 x i32> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i32 = load <16 x i32>, ptr %p, align 64 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_0 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_1 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_2 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i32_3 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_0 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_1 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_2 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_3 = shufflevector <16 x i32> %v4i32, <16 x i32> undef, <4 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i32 = load <32 x i32>, ptr %p, align 128 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_0 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_1 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_2 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i32_3 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_0 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_1 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_2 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_3 = shufflevector <32 x i32> %v8i32, <32 x i32> undef, <8 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i32 = load <64 x i32>, ptr %p, align 256 -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_0 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_1 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_2 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> -; CODESIZE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i32_3 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_0 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_1 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_2 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> +; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_3 = shufflevector <64 x i32> %v16i32, <64 x i32> undef, <16 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i64 = load <8 x i64>, ptr %p, align 64 ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_0 = shufflevector <8 x i64> %v2i64, <8 x i64> undef, <2 x i32> ; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_1 = shufflevector <8 x i64> %v2i64, <8 x i64> undef, <2 x i32> -- GitLab From 6309440c218778db027306826993e484eab2be17 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sun, 21 Apr 2024 22:41:32 +0800 Subject: [PATCH 108/357] [InstCombine] Fix unexpected overwriting in `foldSelectWithSRem` (#89539) Fixes #89516 --- .../InstCombine/InstCombineSelect.cpp | 2 +- .../Transforms/InstCombine/select-divrem.ll | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 0262af28068b..73600206a55c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2720,7 +2720,7 @@ static Instruction *foldSelectWithSRem(SelectInst &SI, InstCombinerImpl &IC, // %cnd = icmp slt i32 %rem, 0 // %add = add i32 %rem, %n // %sel = select i1 %cnd, i32 %add, i32 %rem - if (match(TrueVal, m_Add(m_Value(RemRes), m_Value(Remainder))) && + if (match(TrueVal, m_Add(m_Specific(RemRes), m_Value(Remainder))) && match(RemRes, m_SRem(m_Value(Op), m_Specific(Remainder))) && IC.isKnownToBeAPowerOfTwo(Remainder, /*OrZero*/ true) && FalseVal == RemRes) diff --git a/llvm/test/Transforms/InstCombine/select-divrem.ll b/llvm/test/Transforms/InstCombine/select-divrem.ll index f007c53359ca..e0c460c37451 100644 --- a/llvm/test/Transforms/InstCombine/select-divrem.ll +++ b/llvm/test/Transforms/InstCombine/select-divrem.ll @@ -343,3 +343,20 @@ define i32 @rem_euclid_pow2_false_arm_folded(i32 %n) { %res = select i1 %nonneg, i32 %rem, i32 1 ret i32 %res } + +define i8 @pr89516(i8 %n, i8 %x) { +; CHECK-LABEL: @pr89516( +; CHECK-NEXT: [[COND:%.*]] = icmp slt i8 [[X:%.*]], 0 +; CHECK-NEXT: [[POW2:%.*]] = shl nuw i8 1, [[N:%.*]] +; CHECK-NEXT: [[SREM:%.*]] = srem i8 1, [[POW2]] +; CHECK-NEXT: [[ADD:%.*]] = select i1 [[COND]], i8 [[POW2]], i8 0 +; CHECK-NEXT: [[RES:%.*]] = add nuw i8 [[SREM]], [[ADD]] +; CHECK-NEXT: ret i8 [[RES]] +; + %cond = icmp slt i8 %x, 0 + %pow2 = shl nuw i8 1, %n + %srem = srem i8 1, %pow2 + %add = add nuw i8 %srem, %pow2 + %res = select i1 %cond, i8 %add, i8 %srem + ret i8 %res +} -- GitLab From d674f45d51bffbba474b12e07f7d57a2390d2f31 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 21 Apr 2024 08:21:23 -0700 Subject: [PATCH 109/357] [Transforms] Remove extraneous ArrayRef (NFC) (#89535) We don't need to create these instances of ArrayRef because ConstantDataVector::get takes ArrayRef, and ArrayRef can be implicitly constructed from C arrays. --- llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | 6 ++---- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index cdd891fc8948..54b51b520369 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -3201,8 +3201,7 @@ Value *DFSanVisitor::makeAddAcquireOrderingTable(IRBuilder<> &IRB) { OrderingTable[(int)AtomicOrderingCABI::seq_cst] = (int)AtomicOrderingCABI::seq_cst; - return ConstantDataVector::get(IRB.getContext(), - ArrayRef(OrderingTable, NumOrderings)); + return ConstantDataVector::get(IRB.getContext(), OrderingTable); } void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) { @@ -3245,8 +3244,7 @@ Value *DFSanVisitor::makeAddReleaseOrderingTable(IRBuilder<> &IRB) { OrderingTable[(int)AtomicOrderingCABI::seq_cst] = (int)AtomicOrderingCABI::seq_cst; - return ConstantDataVector::get(IRB.getContext(), - ArrayRef(OrderingTable, NumOrderings)); + return ConstantDataVector::get(IRB.getContext(), OrderingTable); } void DFSanVisitor::visitLibAtomicStore(CallBase &CB) { diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 1d7d0356ea69..b1fd64fa3b29 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2131,8 +2131,7 @@ struct MemorySanitizerVisitor : public InstVisitor { OrderingTable[(int)AtomicOrderingCABI::seq_cst] = (int)AtomicOrderingCABI::seq_cst; - return ConstantDataVector::get(IRB.getContext(), - ArrayRef(OrderingTable, NumOrderings)); + return ConstantDataVector::get(IRB.getContext(), OrderingTable); } AtomicOrdering addAcquireOrdering(AtomicOrdering a) { @@ -2166,8 +2165,7 @@ struct MemorySanitizerVisitor : public InstVisitor { OrderingTable[(int)AtomicOrderingCABI::seq_cst] = (int)AtomicOrderingCABI::seq_cst; - return ConstantDataVector::get(IRB.getContext(), - ArrayRef(OrderingTable, NumOrderings)); + return ConstantDataVector::get(IRB.getContext(), OrderingTable); } // ------------------- Visitors. -- GitLab From 48324f0f7b26b981e0f68e0faf9bb05d4a0e0fbb Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 21 Apr 2024 09:57:01 -0700 Subject: [PATCH 110/357] [ValueTracking] Combine variable declaration with its only assignment. NFC (#89526) --- llvm/lib/Analysis/ValueTracking.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index c038f7eaabbb..21e3f8a4cc52 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2682,7 +2682,6 @@ static bool isKnownNonZeroFromOperator(const Operator *I, if (cast(I)->isExact()) return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth); - std::optional XUgeY; KnownBits XKnown = computeKnownBits(I->getOperand(0), DemandedElts, Depth, Q); // If X is fully unknown we won't be able to figure anything out so don't @@ -2698,7 +2697,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I, YKnown = YKnown.abs(/*IntMinIsPoison*/ false); } // If X u>= Y then div is non zero (0/0 is UB). - XUgeY = KnownBits::uge(XKnown, YKnown); + std::optional XUgeY = KnownBits::uge(XKnown, YKnown); // If X is total unknown or X u< Y we won't be able to prove non-zero // with compute known bits so just return early. return XUgeY && *XUgeY; -- GitLab From ec062f5b33ed22c61742e3c1486f6cba915801e0 Mon Sep 17 00:00:00 2001 From: Freddy Ye Date: Mon, 22 Apr 2024 10:16:08 +0800 Subject: [PATCH 111/357] [X86][MC] Error out for CMPCCXADD on 32 bit targets. (#88672) This resolves issue #88501. --- llvm/lib/Target/X86/X86InstrAsmAlias.td | 20 ++++++++++--------- llvm/test/MC/X86/apx/cmpccxadd-att.s | 6 +++--- ...d-att-64-alias.s => cmpccxadd-att-alias.s} | 0 .../{cmpccxadd-att-64.s => cmpccxadd-att.s} | 10 +++++++--- ...tel-64-alias.s => cmpccxadd-intel-alias.s} | 0 ...cmpccxadd-intel-64.s => cmpccxadd-intel.s} | 0 6 files changed, 21 insertions(+), 15 deletions(-) rename llvm/test/MC/X86/{cmpccxadd-att-64-alias.s => cmpccxadd-att-alias.s} (100%) rename llvm/test/MC/X86/{cmpccxadd-att-64.s => cmpccxadd-att.s} (99%) rename llvm/test/MC/X86/{cmpccxadd-intel-64-alias.s => cmpccxadd-intel-alias.s} (100%) rename llvm/test/MC/X86/{cmpccxadd-intel-64.s => cmpccxadd-intel.s} (100%) diff --git a/llvm/lib/Target/X86/X86InstrAsmAlias.td b/llvm/lib/Target/X86/X86InstrAsmAlias.td index f67c03f98e87..493adbb5b9d4 100644 --- a/llvm/lib/Target/X86/X86InstrAsmAlias.td +++ b/llvm/lib/Target/X86/X86InstrAsmAlias.td @@ -51,15 +51,17 @@ def : InstAlias<"invlpgb\t{%rax, %edx|rax, edx}", (INVLPGB64)>, Requires<[In64Bi // CMPCCXADD Instructions Alias multiclass CMPCCXADD_Aliases { - def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", - (CMPCCXADDmr32 GR32:$dst, i32mem:$dstsrc2, GR32:$src3, CC), 0>; - def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", - (CMPCCXADDmr64 GR64:$dst, i64mem:$dstsrc2, GR64:$src3, CC), 0>; - - def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", - (CMPCCXADDmr32_EVEX GR32:$dst, i32mem:$dstsrc2, GR32:$src3, CC), 0>; - def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", - (CMPCCXADDmr64_EVEX GR64:$dst, i64mem:$dstsrc2, GR64:$src3, CC), 0>; + let Predicates = [In64BitMode] in { + def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", + (CMPCCXADDmr32 GR32:$dst, i32mem:$dstsrc2, GR32:$src3, CC), 0>; + def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", + (CMPCCXADDmr64 GR64:$dst, i64mem:$dstsrc2, GR64:$src3, CC), 0>; + + def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", + (CMPCCXADDmr32_EVEX GR32:$dst, i32mem:$dstsrc2, GR32:$src3, CC), 0>; + def : InstAlias<"cmp"#Cond#"xadd"#"\t{$src3, $dst, $dstsrc2|$dstsrc2, $dst, $src3}", + (CMPCCXADDmr64_EVEX GR64:$dst, i64mem:$dstsrc2, GR64:$src3, CC), 0>; + } } // CCMP Instructions Alias diff --git a/llvm/test/MC/X86/apx/cmpccxadd-att.s b/llvm/test/MC/X86/apx/cmpccxadd-att.s index 0a21abbd0ed2..d6ade869ca1d 100644 --- a/llvm/test/MC/X86/apx/cmpccxadd-att.s +++ b/llvm/test/MC/X86/apx/cmpccxadd-att.s @@ -3,9 +3,9 @@ # ERROR-COUNT-60: error: # ERROR-NOT: error: -# CHECK: {evex} cmpnbexadd %ecx, %edx, 123(%rax,%rbx,4) -# CHECK: encoding: [0x62,0xf2,0x75,0x08,0xe7,0x54,0x98,0x7b] - {evex} cmpnbexadd %ecx, %edx, 123(%rax,%rbx,4) +# CHECK: {evex} cmpnbexadd %ecx, %edx, 123(%eax,%ebx,4) +# CHECK: encoding: [0x67,0x62,0xf2,0x75,0x08,0xe7,0x54,0x98,0x7b] + {evex} cmpnbexadd %ecx, %edx, 123(%eax,%ebx,4) # CHECK: {evex} cmpnbexadd %r9, %r15, 123(%rax,%rbx,4) # CHECK: encoding: [0x62,0x72,0xb5,0x08,0xe7,0x7c,0x98,0x7b] diff --git a/llvm/test/MC/X86/cmpccxadd-att-64-alias.s b/llvm/test/MC/X86/cmpccxadd-att-alias.s similarity index 100% rename from llvm/test/MC/X86/cmpccxadd-att-64-alias.s rename to llvm/test/MC/X86/cmpccxadd-att-alias.s diff --git a/llvm/test/MC/X86/cmpccxadd-att-64.s b/llvm/test/MC/X86/cmpccxadd-att.s similarity index 99% rename from llvm/test/MC/X86/cmpccxadd-att-64.s rename to llvm/test/MC/X86/cmpccxadd-att.s index 2ef49cba92e3..c79cc55a15b8 100644 --- a/llvm/test/MC/X86/cmpccxadd-att-64.s +++ b/llvm/test/MC/X86/cmpccxadd-att.s @@ -1,4 +1,8 @@ // RUN: llvm-mc -triple x86_64 --show-encoding %s | FileCheck %s +// RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR + +// ERROR-COUNT-193: error: +// ERROR-NOT: error: // CHECK: cmpbexadd %eax, %ecx, 268435456(%rbp,%r14,8) // CHECK: encoding: [0xc4,0xa2,0x79,0xe6,0x8c,0xf5,0x00,0x00,0x00,0x10] @@ -20,9 +24,9 @@ // CHECK: encoding: [0xc4,0xe2,0x79,0xe6,0x89,0xfc,0x01,0x00,0x00] cmpbexadd %eax, %ecx, 508(%rcx) -// CHECK: cmpbexadd %eax, %ecx, -512(%rdx) -// CHECK: encoding: [0xc4,0xe2,0x79,0xe6,0x8a,0x00,0xfe,0xff,0xff] - cmpbexadd %eax, %ecx, -512(%rdx) +// CHECK: cmpbexadd %eax, %ecx, -512(%edx) +// CHECK: encoding: [0x67,0xc4,0xe2,0x79,0xe6,0x8a,0x00,0xfe,0xff,0xff] + cmpbexadd %eax, %ecx, -512(%edx) // CHECK: cmpbexadd %r10, %r9, 268435456(%rbp,%r14,8) // CHECK: encoding: [0xc4,0x22,0xa9,0xe6,0x8c,0xf5,0x00,0x00,0x00,0x10] diff --git a/llvm/test/MC/X86/cmpccxadd-intel-64-alias.s b/llvm/test/MC/X86/cmpccxadd-intel-alias.s similarity index 100% rename from llvm/test/MC/X86/cmpccxadd-intel-64-alias.s rename to llvm/test/MC/X86/cmpccxadd-intel-alias.s diff --git a/llvm/test/MC/X86/cmpccxadd-intel-64.s b/llvm/test/MC/X86/cmpccxadd-intel.s similarity index 100% rename from llvm/test/MC/X86/cmpccxadd-intel-64.s rename to llvm/test/MC/X86/cmpccxadd-intel.s -- GitLab From 2a47ee070145438424b065a35c4a680ea0cb0c1f Mon Sep 17 00:00:00 2001 From: donald chen <62002319+cxy-1993@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:53:59 +0800 Subject: [PATCH 112/357] [MLIR][Linalg] Enable fuse consumer (#85528) This patch adds support for consumer fusion to the tiling interface, and implements fuse consumers on FuseIntoContainingOp. - Add interface method 'getIterDomainTilePositionFromOperandPosition' to tiling interface which get iteration domain position from operand position. - Add interface method 'getTiledImplementationFromOperandPosition' to tiling interface which generate tiled implementation according to operand position. - Implemented the above two methods and supported consumer fusion for FuseIntoContainingOp. Signed-off-by: Donald Chen --- .../mlir/Interfaces/TilingInterface.td | 67 ++++++++++- mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 4 +- .../Linalg/Transforms/TilingInterfaceImpl.cpp | 106 +++++++++++++----- .../Tensor/IR/TensorTilingInterfaceImpl.cpp | 12 +- 4 files changed, 149 insertions(+), 40 deletions(-) diff --git a/mlir/include/mlir/Interfaces/TilingInterface.td b/mlir/include/mlir/Interfaces/TilingInterface.td index 66382f29c242..84f7dec2f400 100644 --- a/mlir/include/mlir/Interfaces/TilingInterface.td +++ b/mlir/include/mlir/Interfaces/TilingInterface.td @@ -63,7 +63,7 @@ def TilingInterface : OpInterface<"TilingInterface"> { The method returns the operation that is the tiled implementation. }], - /*retType=*/"FailureOr", + /*retType=*/"FailureOr<::mlir::TilingResult>", /*methodName=*/"getTiledImplementation", /*args=*/(ins "OpBuilder &":$b, @@ -82,15 +82,34 @@ def TilingInterface : OpInterface<"TilingInterface"> { by the tiled implementation. Expects the same `offsets` and `sizes` as used to obtain the tiled implementation of the operation. }], - /*retType=*/"LogicalResult", + /*retType=*/"::mlir::LogicalResult", /*methodName=*/"getResultTilePosition", /*args=*/(ins "OpBuilder &":$b, "unsigned":$resultNumber, "ArrayRef ":$offsets, "ArrayRef ":$sizes, - "SmallVector &":$resultOffsets, - "SmallVector &":$resultSizes), + "SmallVectorImpl &":$resultOffsets, + "SmallVectorImpl &":$resultSizes), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return failure(); + }] + >, + InterfaceMethod< + /*desc=*/[{ + Method to return the position of iteration domain tile computed by the + tiled operation. + }], + /*retType=*/"::mlir::LogicalResult", + /*methodName=*/"getIterationDomainTileFromOperandTile", + /*args=*/(ins + "OpBuilder &":$b, + "unsigned":$operandNumber, + "ArrayRef ":$offsets, + "ArrayRef ":$sizes, + "SmallVectorImpl &":$iterDomainOffsets, + "SmallVectorImpl &":$iterDomainSizes), /*methodBody=*/"", /*defaultImplementation=*/[{ return failure(); @@ -119,7 +138,7 @@ def TilingInterface : OpInterface<"TilingInterface"> { iteration space). - `sizes` provides the size of the tile. }], - /*retType=*/"FailureOr", + /*retType=*/"FailureOr<::mlir::TilingResult>", /*methodName=*/"generateResultTileValue", /*args=*/(ins "OpBuilder &":$b, @@ -131,6 +150,42 @@ def TilingInterface : OpInterface<"TilingInterface"> { return failure(); }] >, + InterfaceMethod< + /*desc=*/[{ + Method to generate the tiled implementation of an operation from + operand tile position. + + Generates the IR that computes the tiled implementation of an + operation from operand tile. The `offsets` and `sizes` + describe the tile of the operand required. This is different from + `getTiledImplementation` which generates the tiled + implementation of the operation given a tile of the + iteration space. This method generates a tiled + implementation of the operation based on the tile of the + operand required. This method enables consumer fusion by using + tile and fuse. The method returns failure if the operation + can't be tiled to generate the operand tile. In practical terms + this implies it cannot be tiled and fused with its producers. + + - `offsets` provides the offset of the tile in the coordinate system + of the original iteration space, i.e., if an iteration space + dimension had non-zero offset, it must be included in the offset + provided here (as opposed to zero-based offset "relative" to the + iteration space). + - `sizes` provides the size of the tile. + }], + /*retType=*/"FailureOr<::mlir::TilingResult>", + /*methodName=*/"getTiledImplementationFromOperandTile", + /*args=*/(ins + "OpBuilder &":$b, + "unsigned":$operandNumber, + "ArrayRef":$offsets, + "ArrayRef":$sizes), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return failure(); + }] + >, InterfaceMethod< /*desc=*/[{ Generates the scalar implementation of the operation. @@ -142,7 +197,7 @@ def TilingInterface : OpInterface<"TilingInterface"> { transformations are done, this method can be used to lower to scalar code that can then be lowered to LLVM or SPIR-V dialects. }], - /*retType=*/"LogicalResult", + /*retType=*/"::mlir::LogicalResult", /*methodName=*/"generateScalarImplementation", /*args=*/(ins "OpBuilder &":$b, diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp index 9c5c58fa1fab..e9999c34d0fa 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -2425,8 +2425,8 @@ SoftmaxOp::getTiledImplementation(OpBuilder &builder, LogicalResult SoftmaxOp::getResultTilePosition( OpBuilder &builder, unsigned resultNumber, ArrayRef offsets, - ArrayRef sizes, SmallVector &resultOffsets, - SmallVector &resultSizes) { + ArrayRef sizes, SmallVectorImpl &resultOffsets, + SmallVectorImpl &resultSizes) { if (resultNumber == 0) { resultOffsets.assign(offsets.begin(), offsets.end()); resultSizes.assign(sizes.begin(), sizes.end()); diff --git a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp index bd870d4f982e..71e9c3771dcd 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp @@ -110,7 +110,7 @@ struct LinalgOpTilingInterface })); } - // Instantiate the tiled implementation of the operation. + /// Instantiate the tiled implementation of the operation. FailureOr getTiledImplementation(Operation *op, OpBuilder &b, ArrayRef offsets, @@ -132,14 +132,66 @@ struct LinalgOpTilingInterface return TilingResult{{tiledOp}, SmallVector(tiledOp->getResults())}; } - // Return the details of the output tile generated by the tiled - // implementation. + void + getMappedOffsetAndSize(LinalgOp linalgOp, OpBuilder &b, AffineMap indexingMap, + ArrayRef offsets, + ArrayRef sizes, + SmallVectorImpl &mappedOffsets, + SmallVectorImpl &mappedSizes) const { + unsigned numLoops = linalgOp.getNumLoops(); + auto tilingInterfaceOp = cast(linalgOp.getOperation()); + mappedOffsets.resize(numLoops); + mappedSizes.resize(numLoops); + if (!indexingMap.isPermutation()) { + SmallVector iterationDomain = + tilingInterfaceOp.getIterationDomain(b); + for (const auto &&[index, value] : llvm::enumerate(iterationDomain)) { + mappedOffsets[index] = value.offset; + mappedSizes[index] = value.size; + } + } + for (const auto &&[index, value] : + llvm::enumerate(indexingMap.getResults())) { + unsigned dimPosition = cast(value).getPosition(); + mappedOffsets[dimPosition] = offsets[index]; + mappedSizes[dimPosition] = sizes[index]; + } + } + + /// Return the details of the output tile generated by the tiled + /// implementation. + LogicalResult getIterationDomainTileFromOperandTile( + Operation *op, OpBuilder &b, unsigned operandNumber, + ArrayRef offsets, ArrayRef sizes, + SmallVectorImpl &iterDomainOffsets, + SmallVectorImpl &iterDomainSizes) const { + auto linalgOp = cast(op); + + // Check that the indexing map used for the operand is a projected + // permutation. This could be relaxed with a more general approach that can + // map the offsets and sizes from the operand to iteration space tiles + // (filling in full extent for dimensions not used to access the result). + AffineMap indexingMap = + linalgOp.getMatchingIndexingMap(&op->getOpOperand(operandNumber)); + if (!indexingMap.isProjectedPermutation()) { + return emitError(op->getLoc(), + "unhandled get iter domain position when operand is not " + "accessed using a permuted projection"); + } + + getMappedOffsetAndSize(linalgOp, b, indexingMap, offsets, sizes, + iterDomainOffsets, iterDomainSizes); + return success(); + } + + /// Return the details of the output tile generated by the tiled + /// implementation. LogicalResult getResultTilePosition(Operation *op, OpBuilder &b, unsigned resultNumber, ArrayRef offsets, ArrayRef sizes, - SmallVector &resultOffsets, - SmallVector &resultSizes) const { + SmallVectorImpl &resultOffsets, + SmallVectorImpl &resultSizes) const { Location loc = op->getLoc(); LinalgOp linalgOp = cast(op); @@ -160,6 +212,21 @@ struct LinalgOpTilingInterface return success(); } + FailureOr getTiledImplementationFromOperandTile( + Operation *op, OpBuilder &b, unsigned operandNumber, + ArrayRef offsets, ArrayRef sizes) const { + SmallVector mappedOffsets, mappedSizes; + auto tilingInterfaceOp = cast(op); + if (failed(tilingInterfaceOp.getIterationDomainTileFromOperandTile( + b, operandNumber, offsets, sizes, mappedOffsets, mappedSizes))) { + return emitError( + op->getLoc(), + "unable to obtain the iter domain position of the operation."); + } + return tilingInterfaceOp.getTiledImplementation(b, mappedOffsets, + mappedSizes); + } + FailureOr generateResultTileValue(Operation *op, OpBuilder &b, unsigned resultNumber, ArrayRef offsets, @@ -177,29 +244,16 @@ struct LinalgOpTilingInterface "unhandled tiled implementation generation when result is not " "accessed using a permuted projection"); } - - auto numLoops = linalgOp.getNumLoops(); + SmallVector mappedOffsets, mappedSizes; + getMappedOffsetAndSize(linalgOp, b, indexingMap, offsets, sizes, + mappedOffsets, mappedSizes); auto tilingInterfaceOp = cast(op); - SmallVector iterationTileOffsets(numLoops), - iterationTileSizes(numLoops); - if (!indexingMap.isPermutation()) { - SmallVector iterationDomain = - tilingInterfaceOp.getIterationDomain(b); - for (const auto &range : llvm::enumerate(iterationDomain)) { - iterationTileOffsets[range.index()] = range.value().offset; - iterationTileSizes[range.index()] = range.value().size; - } - } - for (const auto &resultExpr : llvm::enumerate(indexingMap.getResults())) { - unsigned dimPosition = - cast(resultExpr.value()).getPosition(); - iterationTileOffsets[dimPosition] = offsets[resultExpr.index()]; - iterationTileSizes[dimPosition] = sizes[resultExpr.index()]; - } - FailureOr tilingResult = - tilingInterfaceOp.getTiledImplementation(b, iterationTileOffsets, - iterationTileSizes); + tilingInterfaceOp.getTiledImplementation(b, mappedOffsets, mappedSizes); + + if (failed(tilingResult)) + return failure(); + if (tilingResult->tiledOps.size() != 1) return op->emitOpError("failed to generate tiled implementation"); diff --git a/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp b/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp index d25efcf50ec5..296c5fc7a5c2 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp @@ -61,8 +61,8 @@ struct PadOpTiling : public TilingInterface::ExternalModel { getResultTilePosition(Operation *op, OpBuilder &b, unsigned resultNumber, ArrayRef offsets, ArrayRef sizes, - SmallVector &resultOffsets, - SmallVector &resultSizes) const { + SmallVectorImpl &resultOffsets, + SmallVectorImpl &resultSizes) const { resultOffsets.assign(offsets.begin(), offsets.end()); resultSizes.assign(sizes.begin(), sizes.end()); return success(); @@ -199,8 +199,8 @@ struct PackOpTiling getResultTilePosition(Operation *op, OpBuilder &b, unsigned resultNumber, ArrayRef offsets, ArrayRef sizes, - SmallVector &resultOffsets, - SmallVector &resultSizes) const { + SmallVectorImpl &resultOffsets, + SmallVectorImpl &resultSizes) const { // The iteration domain is over outer dimensions of packed layout. In this // context, the outer dimensions of `resultOffsets` are `offsets`. The // inner dimensions of `resultOffsets` are zeros because tiling is not @@ -452,8 +452,8 @@ struct UnPackOpTiling getResultTilePosition(Operation *op, OpBuilder &b, unsigned resultNumber, ArrayRef offsets, ArrayRef sizes, - SmallVector &resultOffsets, - SmallVector &resultSizes) const { + SmallVectorImpl &resultOffsets, + SmallVectorImpl &resultSizes) const { resultOffsets = llvm::to_vector(offsets); resultSizes = llvm::to_vector(sizes); return success(); -- GitLab From e86ebe4ff8705ef30b332e2104ed1c84fc729966 Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Mon, 22 Apr 2024 08:59:18 +0200 Subject: [PATCH 113/357] [LTO] Allow target-specific module splittting (#83128) Allow targets to implement custom module splitting logic for --lto-partitions, see #89245 https://discourse.llvm.org/t/rfc-lto-target-specific-module-splittting/77252 --- llvm/include/llvm/Target/TargetMachine.h | 12 +++ llvm/lib/LTO/LTOBackend.cpp | 13 ++- .../tools/llvm-split/target-specific-split.ll | 10 ++ llvm/tools/llvm-split/CMakeLists.txt | 7 ++ llvm/tools/llvm-split/llvm-split.cpp | 98 ++++++++++++++----- 5 files changed, 111 insertions(+), 29 deletions(-) create mode 100644 llvm/test/tools/llvm-split/target-specific-split.ll diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index ceb371bdc734..48ea3cfe0277 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -418,6 +418,18 @@ public: virtual unsigned getAddressSpaceForPseudoSourceKind(unsigned Kind) const { return 0; } + + /// Entry point for module splitting. Targets can implement custom module + /// splitting logic, mainly used by LTO for --lto-partitions. + /// + /// \returns `true` if the module was split, `false` otherwise. When `false` + /// is returned, it is assumed that \p ModuleCallback has never been called + /// and \p M has not been modified. + virtual bool splitModule( + Module &M, unsigned NumParts, + function_ref MPart)> ModuleCallback) const { + return false; + } }; /// This class describes a target machine that is implemented with the LLVM diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 71e8849dc3cc..d4b89ede2d71 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -436,8 +436,7 @@ static void splitCodeGen(const Config &C, TargetMachine *TM, unsigned ThreadCount = 0; const Target *T = &TM->getTarget(); - SplitModule( - Mod, ParallelCodeGenParallelismLevel, + const auto HandleModulePartition = [&](std::unique_ptr MPart) { // We want to clone the module in a new context to multi-thread the // codegen. We do it by serializing partition modules to bitcode @@ -469,8 +468,14 @@ static void splitCodeGen(const Config &C, TargetMachine *TM, // Pass BC using std::move to ensure that it get moved rather than // copied into the thread's context. std::move(BC), ThreadCount++); - }, - false); + }; + + // Try target-specific module splitting first, then fallback to the default. + if (!TM->splitModule(Mod, ParallelCodeGenParallelismLevel, + HandleModulePartition)) { + SplitModule(Mod, ParallelCodeGenParallelismLevel, HandleModulePartition, + false); + } // Because the inner lambda (which runs in a worker thread) captures our local // variables, we need to wait for the worker threads to terminate before we diff --git a/llvm/test/tools/llvm-split/target-specific-split.ll b/llvm/test/tools/llvm-split/target-specific-split.ll new file mode 100644 index 000000000000..ea4d38084d75 --- /dev/null +++ b/llvm/test/tools/llvm-split/target-specific-split.ll @@ -0,0 +1,10 @@ +; RUN: llvm-split -o %t %s -mtriple x86_64 -preserve-locals 2>&1 | FileCheck %s + +; Basic test for a target that doesn't support target-specific module splitting. + +; CHECK: warning: -preserve-locals has no effect when using TargetMachine::splitModule +; CHECK: warning: TargetMachine::splitModule failed, falling back to default splitModule implementation + +define void @bar() { + ret void +} diff --git a/llvm/tools/llvm-split/CMakeLists.txt b/llvm/tools/llvm-split/CMakeLists.txt index 52eedeb9f53f..0579298462d1 100644 --- a/llvm/tools/llvm-split/CMakeLists.txt +++ b/llvm/tools/llvm-split/CMakeLists.txt @@ -1,9 +1,16 @@ set(LLVM_LINK_COMPONENTS + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos TransformUtils BitWriter + CodeGen Core IRReader + MC Support + Target ) add_llvm_tool(llvm-split diff --git a/llvm/tools/llvm-split/llvm-split.cpp b/llvm/tools/llvm-split/llvm-split.cpp index c6e20e0373c7..41f392bcc531 100644 --- a/llvm/tools/llvm-split/llvm-split.cpp +++ b/llvm/tools/llvm-split/llvm-split.cpp @@ -1,4 +1,4 @@ -//===-- llvm-split: command line tool for testing module splitter ---------===// +//===-- llvm-split: command line tool for testing module splitting --------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// // -// This program can be used to test the llvm::SplitModule function. +// This program can be used to test the llvm::SplitModule and +// TargetMachine::splitModule functions. // //===----------------------------------------------------------------------===// @@ -15,12 +16,17 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/InitLLVM.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/SplitModule.h" using namespace llvm; @@ -47,12 +53,42 @@ static cl::opt cl::desc("Split without externalizing locals"), cl::cat(SplitCategory)); +static cl::opt + MTriple("mtriple", + cl::desc("Target triple. When present, a TargetMachine is created " + "and TargetMachine::splitModule is used instead of the " + "common SplitModule logic."), + cl::value_desc("triple"), cl::cat(SplitCategory)); + +static cl::opt + MCPU("mcpu", cl::desc("Target CPU, ignored if -mtriple is not used"), + cl::value_desc("cpu"), cl::cat(SplitCategory)); + int main(int argc, char **argv) { + InitLLVM X(argc, argv); + LLVMContext Context; SMDiagnostic Err; cl::HideUnrelatedOptions({&SplitCategory, &getColorCategory()}); cl::ParseCommandLineOptions(argc, argv, "LLVM module splitter\n"); + TargetMachine *TM = nullptr; + if (!MTriple.empty()) { + InitializeAllTargets(); + InitializeAllTargetMCs(); + + std::string Error; + const Target *T = TargetRegistry::lookupTarget(MTriple, Error); + if (!T) { + errs() << "unknown target '" << MTriple << "': " << Error << "\n"; + return 1; + } + + TargetOptions Options; + TM = T->createTargetMachine(MTriple, MCPU, /*FS*/ "", Options, std::nullopt, + std::nullopt); + } + std::unique_ptr M = parseIRFile(InputFilename, Err, Context); if (!M) { @@ -61,28 +97,40 @@ int main(int argc, char **argv) { } unsigned I = 0; - SplitModule( - *M, NumOutputs, - [&](std::unique_ptr MPart) { - std::error_code EC; - std::unique_ptr Out(new ToolOutputFile( - OutputFilename + utostr(I++), EC, sys::fs::OF_None)); - if (EC) { - errs() << EC.message() << '\n'; - exit(1); - } - - if (verifyModule(*MPart, &errs())) { - errs() << "Broken module!\n"; - exit(1); - } - - WriteBitcodeToFile(*MPart, Out->os()); - - // Declare success. - Out->keep(); - }, - PreserveLocals); + const auto HandleModulePart = [&](std::unique_ptr MPart) { + std::error_code EC; + std::unique_ptr Out( + new ToolOutputFile(OutputFilename + utostr(I++), EC, sys::fs::OF_None)); + if (EC) { + errs() << EC.message() << '\n'; + exit(1); + } + + if (verifyModule(*MPart, &errs())) { + errs() << "Broken module!\n"; + exit(1); + } + + WriteBitcodeToFile(*MPart, Out->os()); + + // Declare success. + Out->keep(); + }; + + if (TM) { + if (PreserveLocals) { + errs() << "warning: -preserve-locals has no effect when using " + "TargetMachine::splitModule\n"; + } + + if (TM->splitModule(*M, NumOutputs, HandleModulePart)) + return 0; + + errs() << "warning: " + "TargetMachine::splitModule failed, falling back to default " + "splitModule implementation\n"; + } + SplitModule(*M, NumOutputs, HandleModulePart, PreserveLocals); return 0; } -- GitLab From abb958f1610becc0a753ad8f4308a90f85e1338f Mon Sep 17 00:00:00 2001 From: martinboehme Date: Mon, 22 Apr 2024 09:23:13 +0200 Subject: [PATCH 114/357] [clang][dataflow] Model conditional operator correctly. (#89213) --- .../FlowSensitive/DataflowEnvironment.h | 15 +++++ .../clang/Analysis/FlowSensitive/Transfer.h | 3 +- .../FlowSensitive/DataflowEnvironment.cpp | 46 ++++++------- clang/lib/Analysis/FlowSensitive/Transfer.cpp | 57 +++++++++++----- .../TypeErasedDataflowAnalysis.cpp | 4 +- .../Analysis/FlowSensitive/TestingSupport.h | 4 +- .../Analysis/FlowSensitive/TransferTest.cpp | 66 +++++++++++++++++-- 7 files changed, 149 insertions(+), 46 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index d50dba35f826..cdf89c7def2c 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -244,6 +244,21 @@ public: Environment::ValueModel &Model, ExprJoinBehavior ExprBehavior); + /// Returns a value that approximates both `Val1` and `Val2`, or null if no + /// such value can be produced. + /// + /// `Env1` and `Env2` can be used to query child values and path condition + /// implications of `Val1` and `Val2` respectively. The joined value will be + /// produced in `JoinedEnv`. + /// + /// Requirements: + /// + /// `Val1` and `Val2` must model values of type `Type`. + static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1, + Value *Val2, const Environment &Env2, + Environment &JoinedEnv, + Environment::ValueModel &Model); + /// Widens the environment point-wise, using `PrevEnv` as needed to inform the /// approximation. /// diff --git a/clang/include/clang/Analysis/FlowSensitive/Transfer.h b/clang/include/clang/Analysis/FlowSensitive/Transfer.h index ed148250d8eb..940025e02100 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Transfer.h +++ b/clang/include/clang/Analysis/FlowSensitive/Transfer.h @@ -53,7 +53,8 @@ private: /// Requirements: /// /// `S` must not be `ParenExpr` or `ExprWithCleanups`. -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, + Environment::ValueModel &Model); } // namespace dataflow } // namespace clang diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 05395e07a7a6..3cb656adcbdc 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -237,13 +237,8 @@ joinLocToVal(const llvm::MapVector &LocToVal, continue; assert(It->second != nullptr); - if (areEquivalentValues(*Val, *It->second)) { - Result.insert({Loc, Val}); - continue; - } - - if (Value *JoinedVal = joinDistinctValues( - Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) { + if (Value *JoinedVal = Environment::joinValues( + Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) { Result.insert({Loc, JoinedVal}); } } @@ -775,27 +770,16 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal; JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; - if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) { - // `ReturnVal` might not always get set -- for example if we have a return - // statement of the form `return some_other_func()` and we decide not to - // analyze `some_other_func()`. - // In this case, we can't say anything about the joined return value -- we - // don't simply want to propagate the return value that we do have, because - // it might not be the correct one. - // This occurs for example in the test `ContextSensitiveMutualRecursion`. + if (EnvA.CallStack.empty()) { JoinedEnv.ReturnVal = nullptr; - } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) { - JoinedEnv.ReturnVal = EnvA.ReturnVal; } else { - assert(!EnvA.CallStack.empty()); // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this // cast. auto *Func = dyn_cast(EnvA.CallStack.back()); assert(Func != nullptr); - if (Value *JoinedVal = - joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA, - *EnvB.ReturnVal, EnvB, JoinedEnv, Model)) - JoinedEnv.ReturnVal = JoinedVal; + JoinedEnv.ReturnVal = + joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal, + EnvB, JoinedEnv, Model); } if (EnvA.ReturnLoc == EnvB.ReturnLoc) @@ -821,6 +805,24 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, return JoinedEnv; } +Value *Environment::joinValues(QualType Ty, Value *Val1, + const Environment &Env1, Value *Val2, + const Environment &Env2, Environment &JoinedEnv, + Environment::ValueModel &Model) { + if (Val1 == nullptr || Val2 == nullptr) + // We can't say anything about the joined value -- even if one of the values + // is non-null, we don't want to simply propagate it, because it would be + // too specific: Because the other value is null, that means we have no + // information at all about the value (i.e. the value is unconstrained). + return nullptr; + + if (areEquivalentValues(*Val1, *Val2)) + // Arbitrarily return one of the two values. + return Val1; + + return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model); +} + StorageLocation &Environment::createStorageLocation(QualType Type) { return DACtx->createStorageLocation(Type); } diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 2771c8b2e37e..f56fd64296cc 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -124,8 +124,9 @@ namespace { class TransferVisitor : public ConstStmtVisitor { public: - TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env) - : StmtToEnv(StmtToEnv), Env(Env) {} + TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, + Environment::ValueModel &Model) + : StmtToEnv(StmtToEnv), Env(Env), Model(Model) {} void VisitBinaryOperator(const BinaryOperator *S) { const Expr *LHS = S->getLHS(); @@ -641,17 +642,41 @@ public: } void VisitConditionalOperator(const ConditionalOperator *S) { - // FIXME: Revisit this once flow conditions are added to the framework. For - // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow - // condition. - // When we do this, we will need to retrieve the values of the operands from - // the environments for the basic blocks they are computed in, in a similar - // way to how this is done for short-circuited logical operators in - // `getLogicOperatorSubExprValue()`. - if (S->isGLValue()) - Env.setStorageLocation(*S, Env.createObject(S->getType())); - else if (!S->getType()->isRecordType()) { - if (Value *Val = Env.createValue(S->getType())) + const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr()); + const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr()); + + if (TrueEnv == nullptr || FalseEnv == nullptr) { + // We should always have an environment as we should visit the true / + // false branches before the conditional operator. + assert(false); + return; + } + + if (S->isGLValue()) { + StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr()); + StorageLocation *FalseLoc = + FalseEnv->getStorageLocation(*S->getFalseExpr()); + if (TrueLoc == FalseLoc && TrueLoc != nullptr) + Env.setStorageLocation(*S, *TrueLoc); + } else if (!S->getType()->isRecordType()) { + // The conditional operator can evaluate to either of the values of the + // two branches. To model this, join these two values together to yield + // the result of the conditional operator. + // Note: Most joins happen in `computeBlockInputState()`, but this case is + // different: + // - `computeBlockInputState()` (which in turn calls `Environment::join()` + // joins values associated with the _same_ expression or storage + // location, then associates the joined value with that expression or + // storage location. This join has nothing to do with transfer -- + // instead, it joins together the results of performing transfer on two + // different blocks. + // - Here, we join values associated with _different_ expressions (the + // true and false branch), then associate the joined value with a third + // expression (the conditional operator itself). This join is what it + // means to perform transfer on the conditional operator. + if (Value *Val = Environment::joinValues( + S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv, + FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model)) Env.setValue(*S, *Val); } } @@ -810,12 +835,14 @@ private: const StmtToEnvMap &StmtToEnv; Environment &Env; + Environment::ValueModel &Model; }; } // namespace -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) { - TransferVisitor(StmtToEnv, Env).Visit(&S); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, + Environment::ValueModel &Model) { + TransferVisitor(StmtToEnv, Env, Model).Visit(&S); } } // namespace dataflow diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 71d5c1a6c4f4..12eff4dd4b78 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -316,7 +316,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt, const Stmt *S = Elt.getStmt(); assert(S != nullptr); transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S, - InputState.Env); + InputState.Env, AC.Analysis); } /// Built-in transfer function for `CFGInitializer`. @@ -452,7 +452,7 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC, // terminator condition, but not as a `CFGElement`. The condition of an if // statement is one such example. transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State), - *TerminatorCond, State.Env); + *TerminatorCond, State.Env, AC.Analysis); // If the transfer function didn't produce a value, create an atom so that // we have *some* value for the condition expression. This ensures that diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h index e3c7ff685f57..3b0e05ed7222 100644 --- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -456,7 +456,7 @@ const IndirectFieldDecl *findIndirectFieldDecl(ASTContext &ASTCtx, /// Requirements: /// /// `Name` must be unique in `ASTCtx`. -template +template LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env, llvm::StringRef Name) { const ValueDecl *VD = findValueDecl(ASTCtx, Name); @@ -470,7 +470,7 @@ LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env, /// Requirements: /// /// `Name` must be unique in `ASTCtx`. -template +template ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env, llvm::StringRef Name) { const ValueDecl *VD = findValueDecl(ASTCtx, Name); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index bb16138126c8..3a62bc0c0208 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -5275,6 +5275,67 @@ TEST(TransferTest, BinaryOperatorComma) { }); } +TEST(TransferTest, ConditionalOperatorValue) { + std::string Code = R"( + void target(bool Cond, bool B1, bool B2) { + bool JoinSame = Cond ? B1 : B1; + bool JoinDifferent = Cond ? B1 : B2; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); + + auto &B1 = getValueForDecl(ASTCtx, Env, "B1"); + auto &B2 = getValueForDecl(ASTCtx, Env, "B2"); + auto &JoinSame = getValueForDecl(ASTCtx, Env, "JoinSame"); + auto &JoinDifferent = + getValueForDecl(ASTCtx, Env, "JoinDifferent"); + + EXPECT_EQ(&JoinSame, &B1); + + const Formula &JoinDifferentEqB1 = + Env.arena().makeEquals(JoinDifferent.formula(), B1.formula()); + EXPECT_TRUE(Env.allows(JoinDifferentEqB1)); + EXPECT_FALSE(Env.proves(JoinDifferentEqB1)); + + const Formula &JoinDifferentEqB2 = + Env.arena().makeEquals(JoinDifferent.formula(), B2.formula()); + EXPECT_TRUE(Env.allows(JoinDifferentEqB2)); + EXPECT_FALSE(Env.proves(JoinDifferentEqB1)); + }); +} + +TEST(TransferTest, ConditionalOperatorLocation) { + std::string Code = R"( + void target(bool Cond, int I1, int I2) { + int &JoinSame = Cond ? I1 : I1; + int &JoinDifferent = Cond ? I1 : I2; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); + + StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1"); + StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2"); + StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame"); + StorageLocation &JoinDifferent = + getLocForDecl(ASTCtx, Env, "JoinDifferent"); + + EXPECT_EQ(&JoinSame, &I1); + + EXPECT_NE(&JoinDifferent, &I1); + EXPECT_NE(&JoinDifferent, &I2); + }); +} + TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { std::string Code = R"( void target(bool Foo) { @@ -5522,10 +5583,7 @@ TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { auto *Loc = Env.getReturnStorageLocation(); EXPECT_THAT(Loc, NotNull()); - // TODO: We would really like to make this stronger assertion, but that - // doesn't work because we don't propagate values correctly through - // the conditional operator yet. - // EXPECT_EQ(Loc, SLoc); + EXPECT_EQ(Loc, SLoc); }, {BuiltinOptions{ContextSensitiveOptions{}}}); } -- GitLab From 8ff6434546bcb4602bd079f4161f746956905c60 Mon Sep 17 00:00:00 2001 From: martinboehme Date: Mon, 22 Apr 2024 09:35:29 +0200 Subject: [PATCH 115/357] Revert "[clang][dataflow] Model conditional operator correctly." (#89577) Reverts llvm/llvm-project#89213 This is causing buildbot failures. --- .../FlowSensitive/DataflowEnvironment.h | 15 ----- .../clang/Analysis/FlowSensitive/Transfer.h | 3 +- .../FlowSensitive/DataflowEnvironment.cpp | 46 +++++++------ clang/lib/Analysis/FlowSensitive/Transfer.cpp | 57 +++++----------- .../TypeErasedDataflowAnalysis.cpp | 4 +- .../Analysis/FlowSensitive/TestingSupport.h | 4 +- .../Analysis/FlowSensitive/TransferTest.cpp | 66 ++----------------- 7 files changed, 46 insertions(+), 149 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index cdf89c7def2c..d50dba35f826 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -244,21 +244,6 @@ public: Environment::ValueModel &Model, ExprJoinBehavior ExprBehavior); - /// Returns a value that approximates both `Val1` and `Val2`, or null if no - /// such value can be produced. - /// - /// `Env1` and `Env2` can be used to query child values and path condition - /// implications of `Val1` and `Val2` respectively. The joined value will be - /// produced in `JoinedEnv`. - /// - /// Requirements: - /// - /// `Val1` and `Val2` must model values of type `Type`. - static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1, - Value *Val2, const Environment &Env2, - Environment &JoinedEnv, - Environment::ValueModel &Model); - /// Widens the environment point-wise, using `PrevEnv` as needed to inform the /// approximation. /// diff --git a/clang/include/clang/Analysis/FlowSensitive/Transfer.h b/clang/include/clang/Analysis/FlowSensitive/Transfer.h index 940025e02100..ed148250d8eb 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Transfer.h +++ b/clang/include/clang/Analysis/FlowSensitive/Transfer.h @@ -53,8 +53,7 @@ private: /// Requirements: /// /// `S` must not be `ParenExpr` or `ExprWithCleanups`. -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, - Environment::ValueModel &Model); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env); } // namespace dataflow } // namespace clang diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 3cb656adcbdc..05395e07a7a6 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -237,8 +237,13 @@ joinLocToVal(const llvm::MapVector &LocToVal, continue; assert(It->second != nullptr); - if (Value *JoinedVal = Environment::joinValues( - Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) { + if (areEquivalentValues(*Val, *It->second)) { + Result.insert({Loc, Val}); + continue; + } + + if (Value *JoinedVal = joinDistinctValues( + Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) { Result.insert({Loc, JoinedVal}); } } @@ -770,16 +775,27 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal; JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; - if (EnvA.CallStack.empty()) { + if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) { + // `ReturnVal` might not always get set -- for example if we have a return + // statement of the form `return some_other_func()` and we decide not to + // analyze `some_other_func()`. + // In this case, we can't say anything about the joined return value -- we + // don't simply want to propagate the return value that we do have, because + // it might not be the correct one. + // This occurs for example in the test `ContextSensitiveMutualRecursion`. JoinedEnv.ReturnVal = nullptr; + } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) { + JoinedEnv.ReturnVal = EnvA.ReturnVal; } else { + assert(!EnvA.CallStack.empty()); // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this // cast. auto *Func = dyn_cast(EnvA.CallStack.back()); assert(Func != nullptr); - JoinedEnv.ReturnVal = - joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal, - EnvB, JoinedEnv, Model); + if (Value *JoinedVal = + joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA, + *EnvB.ReturnVal, EnvB, JoinedEnv, Model)) + JoinedEnv.ReturnVal = JoinedVal; } if (EnvA.ReturnLoc == EnvB.ReturnLoc) @@ -805,24 +821,6 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB, return JoinedEnv; } -Value *Environment::joinValues(QualType Ty, Value *Val1, - const Environment &Env1, Value *Val2, - const Environment &Env2, Environment &JoinedEnv, - Environment::ValueModel &Model) { - if (Val1 == nullptr || Val2 == nullptr) - // We can't say anything about the joined value -- even if one of the values - // is non-null, we don't want to simply propagate it, because it would be - // too specific: Because the other value is null, that means we have no - // information at all about the value (i.e. the value is unconstrained). - return nullptr; - - if (areEquivalentValues(*Val1, *Val2)) - // Arbitrarily return one of the two values. - return Val1; - - return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model); -} - StorageLocation &Environment::createStorageLocation(QualType Type) { return DACtx->createStorageLocation(Type); } diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index f56fd64296cc..2771c8b2e37e 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -124,9 +124,8 @@ namespace { class TransferVisitor : public ConstStmtVisitor { public: - TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, - Environment::ValueModel &Model) - : StmtToEnv(StmtToEnv), Env(Env), Model(Model) {} + TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env) + : StmtToEnv(StmtToEnv), Env(Env) {} void VisitBinaryOperator(const BinaryOperator *S) { const Expr *LHS = S->getLHS(); @@ -642,41 +641,17 @@ public: } void VisitConditionalOperator(const ConditionalOperator *S) { - const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr()); - const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr()); - - if (TrueEnv == nullptr || FalseEnv == nullptr) { - // We should always have an environment as we should visit the true / - // false branches before the conditional operator. - assert(false); - return; - } - - if (S->isGLValue()) { - StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr()); - StorageLocation *FalseLoc = - FalseEnv->getStorageLocation(*S->getFalseExpr()); - if (TrueLoc == FalseLoc && TrueLoc != nullptr) - Env.setStorageLocation(*S, *TrueLoc); - } else if (!S->getType()->isRecordType()) { - // The conditional operator can evaluate to either of the values of the - // two branches. To model this, join these two values together to yield - // the result of the conditional operator. - // Note: Most joins happen in `computeBlockInputState()`, but this case is - // different: - // - `computeBlockInputState()` (which in turn calls `Environment::join()` - // joins values associated with the _same_ expression or storage - // location, then associates the joined value with that expression or - // storage location. This join has nothing to do with transfer -- - // instead, it joins together the results of performing transfer on two - // different blocks. - // - Here, we join values associated with _different_ expressions (the - // true and false branch), then associate the joined value with a third - // expression (the conditional operator itself). This join is what it - // means to perform transfer on the conditional operator. - if (Value *Val = Environment::joinValues( - S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv, - FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model)) + // FIXME: Revisit this once flow conditions are added to the framework. For + // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow + // condition. + // When we do this, we will need to retrieve the values of the operands from + // the environments for the basic blocks they are computed in, in a similar + // way to how this is done for short-circuited logical operators in + // `getLogicOperatorSubExprValue()`. + if (S->isGLValue()) + Env.setStorageLocation(*S, Env.createObject(S->getType())); + else if (!S->getType()->isRecordType()) { + if (Value *Val = Env.createValue(S->getType())) Env.setValue(*S, *Val); } } @@ -835,14 +810,12 @@ private: const StmtToEnvMap &StmtToEnv; Environment &Env; - Environment::ValueModel &Model; }; } // namespace -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, - Environment::ValueModel &Model) { - TransferVisitor(StmtToEnv, Env, Model).Visit(&S); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) { + TransferVisitor(StmtToEnv, Env).Visit(&S); } } // namespace dataflow diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 12eff4dd4b78..71d5c1a6c4f4 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -316,7 +316,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt, const Stmt *S = Elt.getStmt(); assert(S != nullptr); transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S, - InputState.Env, AC.Analysis); + InputState.Env); } /// Built-in transfer function for `CFGInitializer`. @@ -452,7 +452,7 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC, // terminator condition, but not as a `CFGElement`. The condition of an if // statement is one such example. transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State), - *TerminatorCond, State.Env, AC.Analysis); + *TerminatorCond, State.Env); // If the transfer function didn't produce a value, create an atom so that // we have *some* value for the condition expression. This ensures that diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h index 3b0e05ed7222..e3c7ff685f57 100644 --- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -456,7 +456,7 @@ const IndirectFieldDecl *findIndirectFieldDecl(ASTContext &ASTCtx, /// Requirements: /// /// `Name` must be unique in `ASTCtx`. -template +template LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env, llvm::StringRef Name) { const ValueDecl *VD = findValueDecl(ASTCtx, Name); @@ -470,7 +470,7 @@ LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env, /// Requirements: /// /// `Name` must be unique in `ASTCtx`. -template +template ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env, llvm::StringRef Name) { const ValueDecl *VD = findValueDecl(ASTCtx, Name); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 3a62bc0c0208..bb16138126c8 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -5275,67 +5275,6 @@ TEST(TransferTest, BinaryOperatorComma) { }); } -TEST(TransferTest, ConditionalOperatorValue) { - std::string Code = R"( - void target(bool Cond, bool B1, bool B2) { - bool JoinSame = Cond ? B1 : B1; - bool JoinDifferent = Cond ? B1 : B2; - // [[p]] - } - )"; - runDataflow( - Code, - [](const llvm::StringMap> &Results, - ASTContext &ASTCtx) { - Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); - - auto &B1 = getValueForDecl(ASTCtx, Env, "B1"); - auto &B2 = getValueForDecl(ASTCtx, Env, "B2"); - auto &JoinSame = getValueForDecl(ASTCtx, Env, "JoinSame"); - auto &JoinDifferent = - getValueForDecl(ASTCtx, Env, "JoinDifferent"); - - EXPECT_EQ(&JoinSame, &B1); - - const Formula &JoinDifferentEqB1 = - Env.arena().makeEquals(JoinDifferent.formula(), B1.formula()); - EXPECT_TRUE(Env.allows(JoinDifferentEqB1)); - EXPECT_FALSE(Env.proves(JoinDifferentEqB1)); - - const Formula &JoinDifferentEqB2 = - Env.arena().makeEquals(JoinDifferent.formula(), B2.formula()); - EXPECT_TRUE(Env.allows(JoinDifferentEqB2)); - EXPECT_FALSE(Env.proves(JoinDifferentEqB1)); - }); -} - -TEST(TransferTest, ConditionalOperatorLocation) { - std::string Code = R"( - void target(bool Cond, int I1, int I2) { - int &JoinSame = Cond ? I1 : I1; - int &JoinDifferent = Cond ? I1 : I2; - // [[p]] - } - )"; - runDataflow( - Code, - [](const llvm::StringMap> &Results, - ASTContext &ASTCtx) { - Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); - - StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1"); - StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2"); - StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame"); - StorageLocation &JoinDifferent = - getLocForDecl(ASTCtx, Env, "JoinDifferent"); - - EXPECT_EQ(&JoinSame, &I1); - - EXPECT_NE(&JoinDifferent, &I1); - EXPECT_NE(&JoinDifferent, &I2); - }); -} - TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { std::string Code = R"( void target(bool Foo) { @@ -5583,7 +5522,10 @@ TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { auto *Loc = Env.getReturnStorageLocation(); EXPECT_THAT(Loc, NotNull()); - EXPECT_EQ(Loc, SLoc); + // TODO: We would really like to make this stronger assertion, but that + // doesn't work because we don't propagate values correctly through + // the conditional operator yet. + // EXPECT_EQ(Loc, SLoc); }, {BuiltinOptions{ContextSensitiveOptions{}}}); } -- GitLab From d18ab0e1bd5032d213acb94ef70564d221f63fa7 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 22 Apr 2024 15:37:42 +0800 Subject: [PATCH 116/357] [InstCombine] Fold fabs over selects (#86390) This patch folds fabs over select if it is beneficial. I also tried other interger/fp intrinsics. Only handling fabs shows benefit to some real-world applications. --- .../InstCombine/InstCombineCalls.cpp | 10 ++- llvm/test/Transforms/InstCombine/fabs.ll | 6 +- .../InstCombine/intrinsic-select.ll | 64 +++++++++++++++++++ .../InstCombine/simplify-demanded-fpclass.ll | 24 +++---- 4 files changed, 87 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index e7a2f54f8680..a37a4cde96f8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2501,10 +2501,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { if (match(II->getArgOperand(0), m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal)))) { // fabs (select Cond, TrueC, FalseC) --> select Cond, AbsT, AbsF - if (isa(TVal) && isa(FVal)) { + if (isa(TVal) || isa(FVal)) { CallInst *AbsT = Builder.CreateCall(II->getCalledFunction(), {TVal}); CallInst *AbsF = Builder.CreateCall(II->getCalledFunction(), {FVal}); - return SelectInst::Create(Cond, AbsT, AbsF); + SelectInst *SI = SelectInst::Create(Cond, AbsT, AbsF); + FastMathFlags FMF1 = II->getFastMathFlags(); + FastMathFlags FMF2 = + cast(II->getArgOperand(0))->getFastMathFlags(); + FMF2.setNoSignedZeros(false); + SI->setFastMathFlags(FMF1 | FMF2); + return SI; } // fabs (select Cond, -FVal, FVal) --> fabs FVal if (match(TVal, m_FNeg(m_Specific(FVal)))) diff --git a/llvm/test/Transforms/InstCombine/fabs.ll b/llvm/test/Transforms/InstCombine/fabs.ll index 5ec65784e7a3..cccf0f4457b6 100644 --- a/llvm/test/Transforms/InstCombine/fabs.ll +++ b/llvm/test/Transforms/InstCombine/fabs.ll @@ -179,9 +179,9 @@ define float @fabs_select_constant_neg0(i32 %c) { define float @fabs_select_var_constant_negative(i32 %c, float %x) { ; CHECK-LABEL: @fabs_select_var_constant_negative( ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float [[X:%.*]], float -1.000000e+00 -; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) -; CHECK-NEXT: ret float [[FABS]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT:%.*]]) +; CHECK-NEXT: [[FABS1:%.*]] = select i1 [[CMP]], float [[FABS]], float 1.000000e+00 +; CHECK-NEXT: ret float [[FABS1]] ; %cmp = icmp eq i32 %c, 0 %select = select i1 %cmp, float %x, float -1.0 diff --git a/llvm/test/Transforms/InstCombine/intrinsic-select.ll b/llvm/test/Transforms/InstCombine/intrinsic-select.ll index f37226bbd5b0..1727d8f2758b 100644 --- a/llvm/test/Transforms/InstCombine/intrinsic-select.ll +++ b/llvm/test/Transforms/InstCombine/intrinsic-select.ll @@ -280,3 +280,67 @@ entry: %ret = icmp eq i64 %masked, 0 ret i1 %ret } + +define double @test_fabs_select1(double %a) { +; CHECK-LABEL: @test_fabs_select1( +; CHECK-NEXT: [[COND:%.*]] = fcmp uno double [[A:%.*]], 0.000000e+00 +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND]], double 0x7FF8000000000000, double [[A]] +; CHECK-NEXT: ret double [[SEL1]] +; + %cond = fcmp uno double %a, 0.000000e+00 + %sel1 = select i1 %cond, double 0x7FF8000000000000, double %a + %fabs = call double @llvm.fabs.f64(double %sel1) + %sel2 = select i1 %cond, double %fabs, double %a + ret double %sel2 +} + +define <2 x double> @test_fabs_select1_vec(<2 x double> %a) { +; CHECK-LABEL: @test_fabs_select1_vec( +; CHECK-NEXT: [[COND:%.*]] = fcmp uno <2 x double> [[A:%.*]], zeroinitializer +; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[COND]], <2 x double> , <2 x double> [[A]] +; CHECK-NEXT: ret <2 x double> [[SEL2]] +; + %cond = fcmp uno <2 x double> %a, zeroinitializer + %sel1 = select <2 x i1> %cond, <2 x double> splat(double 0x7FF8000000000000), <2 x double> %a + %fabs = call <2 x double> @llvm.fabs.v2f64(<2 x double> %sel1) + %sel2 = select <2 x i1> %cond, <2 x double> %fabs, <2 x double> %a + ret <2 x double> %sel2 +} + +define double @test_fabs_select2(double %a) { +; CHECK-LABEL: @test_fabs_select2( +; CHECK-NEXT: [[ABS1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[ABS1]], 0x7FF0000000000000 +; CHECK-NEXT: [[ABS2:%.*]] = select i1 [[CMP]], double 0.000000e+00, double [[ABS1]] +; CHECK-NEXT: ret double [[ABS2]] +; + %abs1 = call double @llvm.fabs.f64(double %a) + %cmp = fcmp oeq double %abs1, 0x7FF0000000000000 + %sel = select i1 %cmp, double -0.000000e+00, double %abs1 + %abs2 = call double @llvm.fabs.f64(double %sel) + ret double %abs2 +} + +; nsz flag should be dropped. + +define double @test_fabs_select_fmf1(i1 %cond, double %a) { +; CHECK-LABEL: @test_fabs_select_fmf1( +; CHECK-NEXT: [[A:%.*]] = call double @llvm.fabs.f64(double [[A1:%.*]]) +; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[COND:%.*]], double 0.000000e+00, double [[A]] +; CHECK-NEXT: ret double [[FABS]] +; + %sel1 = select nnan ninf nsz i1 %cond, double 0.0, double %a + %fabs = call double @llvm.fabs.f64(double %sel1) + ret double %fabs +} + +define double @test_fabs_select_fmf2(i1 %cond, double %a) { +; CHECK-LABEL: @test_fabs_select_fmf2( +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]]) +; CHECK-NEXT: [[SEL1:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]] +; CHECK-NEXT: ret double [[SEL1]] +; + %sel1 = select i1 %cond, double 0.0, double %a + %fabs = call nnan ninf nsz double @llvm.fabs.f64(double %sel1) + ret double %fabs +} diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll index 5dfeb0734fbb..a7d01b4f824d 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll @@ -387,8 +387,8 @@ define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs(i1 %cond, f define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs(i1 %cond, float %x) { ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 ; CHECK-NEXT: ret float [[FABS]] ; %select = select i1 %cond, float %x, float 0x7FF0000000000000 @@ -411,8 +411,8 @@ define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__fabs_ define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) { ; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 ; CHECK-NEXT: ret float [[FABS]] ; %select = select i1 %cond, float %x, float 0x7FF0000000000000 @@ -665,8 +665,8 @@ define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__ define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 ; CHECK-NEXT: ret float [[COPYSIGN]] ; %select = select i1 %cond, float %x, float 0x7FF0000000000000 @@ -678,8 +678,8 @@ define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copys define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) +; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[TMP2]], float 0x7FF0000000000000 ; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: ret float [[COPYSIGN]] ; @@ -692,8 +692,8 @@ define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copys define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { ; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 ; CHECK-NEXT: ret float [[COPYSIGN]] ; %select = select i1 %cond, float %x, float 0x7FF0000000000000 @@ -705,8 +705,8 @@ define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_no define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { ; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) +; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[TMP2]], float 0x7FF0000000000000 ; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: ret float [[COPYSIGN]] ; -- GitLab From 83f7a3a21f6cfbc209b3ccf183abc57c8c51fcc9 Mon Sep 17 00:00:00 2001 From: pvanhout Date: Mon, 22 Apr 2024 09:46:36 +0200 Subject: [PATCH 117/357] [llvm-split] Require x86-registered-target for target-specific-split.ll --- llvm/test/tools/llvm-split/target-specific-split.ll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/test/tools/llvm-split/target-specific-split.ll b/llvm/test/tools/llvm-split/target-specific-split.ll index ea4d38084d75..f368a563d977 100644 --- a/llvm/test/tools/llvm-split/target-specific-split.ll +++ b/llvm/test/tools/llvm-split/target-specific-split.ll @@ -1,3 +1,5 @@ +; REQUIRES: x86-registered-target + ; RUN: llvm-split -o %t %s -mtriple x86_64 -preserve-locals 2>&1 | FileCheck %s ; Basic test for a target that doesn't support target-specific module splitting. -- GitLab From a4bacb0f42ee8bd9d09baaae0fc0ff4650fbef2b Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Mon, 22 Apr 2024 03:48:31 -0400 Subject: [PATCH 118/357] [SelectionDAG] Remove redundant KnownBits smin and smax operations (#89519) It turns out that if any of the operations can be zero, and neither of the operands can be proven to be positive, it is possible for smax to be zero, and KnownBits cannot prove otherwise even with KnownBits::smax. In fact, proving it based on the KnownBits itself at that point without increasing the depth is actually, provably impossible. Same with smin. This covers all the possible cases and is proven to be complete. --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 7dbf83b7adee..b63b8b893fdb 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -5399,9 +5399,6 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const { if (Op1.isNonZero() && Op0.isNonZero()) return true; - if (KnownBits::smax(Op0, Op1).isNonZero()) - return true; - return isKnownNeverZero(Op.getOperand(1), Depth + 1) && isKnownNeverZero(Op.getOperand(0), Depth + 1); } @@ -5417,9 +5414,6 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const { if (Op1.isNonZero() && Op0.isNonZero()) return true; - if (KnownBits::smin(Op0, Op1).isNonZero()) - return true; - return isKnownNeverZero(Op.getOperand(1), Depth + 1) && isKnownNeverZero(Op.getOperand(0), Depth + 1); } -- GitLab From 7f975b6b4027c39d0e44e64a1a78d79d724ce8cf Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 22 Apr 2024 08:54:00 +0100 Subject: [PATCH 119/357] [AArch64] Add tests for more undef lanes on zip/uzp. NFC --- llvm/test/CodeGen/AArch64/arm64-uzp.ll | 228 +++++++++++++++---------- llvm/test/CodeGen/AArch64/arm64-zip.ll | 92 +++++++++- 2 files changed, 228 insertions(+), 92 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/arm64-uzp.ll b/llvm/test/CodeGen/AArch64/arm64-uzp.ll index 94f86e7c88ae..6e01ebc95a1c 100644 --- a/llvm/test/CodeGen/AArch64/arm64-uzp.ll +++ b/llvm/test/CodeGen/AArch64/arm64-uzp.ll @@ -1,107 +1,159 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s -define <8 x i8> @vuzpi8(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpi8: -;CHECK: uzp1.8b -;CHECK: uzp2.8b -;CHECK-NEXT: add.8b - %tmp1 = load <8 x i8>, ptr %A - %tmp2 = load <8 x i8>, ptr %B - %tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> - %tmp4 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> - %tmp5 = add <8 x i8> %tmp3, %tmp4 - ret <8 x i8> %tmp5 +define <8 x i8> @vuzpi8(<8 x i8> %A, <8 x i8> %B) nounwind { +; CHECK-LABEL: vuzpi8: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.8b v2, v0, v1 +; CHECK-NEXT: uzp2.8b v0, v0, v1 +; CHECK-NEXT: add.8b v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i8> %A, <8 x i8> %B, <8 x i32> + %tmp4 = shufflevector <8 x i8> %A, <8 x i8> %B, <8 x i32> + %tmp5 = add <8 x i8> %tmp3, %tmp4 + ret <8 x i8> %tmp5 } -define <4 x i16> @vuzpi16(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpi16: -;CHECK: uzp1.4h -;CHECK: uzp2.4h -;CHECK-NEXT: add.4h - %tmp1 = load <4 x i16>, ptr %A - %tmp2 = load <4 x i16>, ptr %B - %tmp3 = shufflevector <4 x i16> %tmp1, <4 x i16> %tmp2, <4 x i32> - %tmp4 = shufflevector <4 x i16> %tmp1, <4 x i16> %tmp2, <4 x i32> - %tmp5 = add <4 x i16> %tmp3, %tmp4 - ret <4 x i16> %tmp5 +define <4 x i16> @vuzpi16(<4 x i16> %A, <4 x i16> %B) nounwind { +; CHECK-LABEL: vuzpi16: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.4h v2, v0, v1 +; CHECK-NEXT: uzp2.4h v0, v0, v1 +; CHECK-NEXT: add.4h v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <4 x i16> %A, <4 x i16> %B, <4 x i32> + %tmp4 = shufflevector <4 x i16> %A, <4 x i16> %B, <4 x i32> + %tmp5 = add <4 x i16> %tmp3, %tmp4 + ret <4 x i16> %tmp5 } -define <16 x i8> @vuzpQi8(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpQi8: -;CHECK: uzp1.16b -;CHECK: uzp2.16b -;CHECK-NEXT: add.16b - %tmp1 = load <16 x i8>, ptr %A - %tmp2 = load <16 x i8>, ptr %B - %tmp3 = shufflevector <16 x i8> %tmp1, <16 x i8> %tmp2, <16 x i32> - %tmp4 = shufflevector <16 x i8> %tmp1, <16 x i8> %tmp2, <16 x i32> - %tmp5 = add <16 x i8> %tmp3, %tmp4 - ret <16 x i8> %tmp5 +define <16 x i8> @vuzpQi8(<16 x i8> %A, <16 x i8> %B) nounwind { +; CHECK-LABEL: vuzpQi8: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.16b v2, v0, v1 +; CHECK-NEXT: uzp2.16b v0, v0, v1 +; CHECK-NEXT: add.16b v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <16 x i8> %A, <16 x i8> %B, <16 x i32> + %tmp4 = shufflevector <16 x i8> %A, <16 x i8> %B, <16 x i32> + %tmp5 = add <16 x i8> %tmp3, %tmp4 + ret <16 x i8> %tmp5 } -define <8 x i16> @vuzpQi16(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpQi16: -;CHECK: uzp1.8h -;CHECK: uzp2.8h -;CHECK-NEXT: add.8h - %tmp1 = load <8 x i16>, ptr %A - %tmp2 = load <8 x i16>, ptr %B - %tmp3 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> - %tmp4 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> - %tmp5 = add <8 x i16> %tmp3, %tmp4 - ret <8 x i16> %tmp5 +define <8 x i16> @vuzpQi16(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vuzpQi16: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.8h v2, v0, v1 +; CHECK-NEXT: uzp2.8h v0, v0, v1 +; CHECK-NEXT: add.8h v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp4 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp5 = add <8 x i16> %tmp3, %tmp4 + ret <8 x i16> %tmp5 } -define <4 x i32> @vuzpQi32(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpQi32: -;CHECK: uzp1.4s -;CHECK: uzp2.4s -;CHECK-NEXT: add.4s - %tmp1 = load <4 x i32>, ptr %A - %tmp2 = load <4 x i32>, ptr %B - %tmp3 = shufflevector <4 x i32> %tmp1, <4 x i32> %tmp2, <4 x i32> - %tmp4 = shufflevector <4 x i32> %tmp1, <4 x i32> %tmp2, <4 x i32> - %tmp5 = add <4 x i32> %tmp3, %tmp4 - ret <4 x i32> %tmp5 +define <4 x i32> @vuzpQi32(<4 x i32> %A, <4 x i32> %B) nounwind { +; CHECK-LABEL: vuzpQi32: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.4s v2, v0, v1 +; CHECK-NEXT: uzp2.4s v0, v0, v1 +; CHECK-NEXT: add.4s v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> + %tmp4 = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> + %tmp5 = add <4 x i32> %tmp3, %tmp4 + ret <4 x i32> %tmp5 } -define <4 x float> @vuzpQf(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpQf: -;CHECK: uzp1.4s -;CHECK: uzp2.4s -;CHECK-NEXT: fadd.4s - %tmp1 = load <4 x float>, ptr %A - %tmp2 = load <4 x float>, ptr %B - %tmp3 = shufflevector <4 x float> %tmp1, <4 x float> %tmp2, <4 x i32> - %tmp4 = shufflevector <4 x float> %tmp1, <4 x float> %tmp2, <4 x i32> - %tmp5 = fadd <4 x float> %tmp3, %tmp4 - ret <4 x float> %tmp5 +define <4 x float> @vuzpQf(<4 x float> %A, <4 x float> %B) nounwind { +; CHECK-LABEL: vuzpQf: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.4s v2, v0, v1 +; CHECK-NEXT: uzp2.4s v0, v0, v1 +; CHECK-NEXT: fadd.4s v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <4 x float> %A, <4 x float> %B, <4 x i32> + %tmp4 = shufflevector <4 x float> %A, <4 x float> %B, <4 x i32> + %tmp5 = fadd <4 x float> %tmp3, %tmp4 + ret <4 x float> %tmp5 } ; Undef shuffle indices should not prevent matching to VUZP: -define <8 x i8> @vuzpi8_undef(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpi8_undef: -;CHECK: uzp1.8b -;CHECK: uzp2.8b -;CHECK-NEXT: add.8b - %tmp1 = load <8 x i8>, ptr %A - %tmp2 = load <8 x i8>, ptr %B - %tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> - %tmp4 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> - %tmp5 = add <8 x i8> %tmp3, %tmp4 - ret <8 x i8> %tmp5 +define <8 x i8> @vuzpi8_undef(<8 x i8> %A, <8 x i8> %B) nounwind { +; CHECK-LABEL: vuzpi8_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.8b v2, v0, v1 +; CHECK-NEXT: uzp2.8b v0, v0, v1 +; CHECK-NEXT: add.8b v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i8> %A, <8 x i8> %B, <8 x i32> + %tmp4 = shufflevector <8 x i8> %A, <8 x i8> %B, <8 x i32> + %tmp5 = add <8 x i8> %tmp3, %tmp4 + ret <8 x i8> %tmp5 } -define <8 x i16> @vuzpQi16_undef(ptr %A, ptr %B) nounwind { -;CHECK-LABEL: vuzpQi16_undef: -;CHECK: uzp1.8h -;CHECK: uzp2.8h -;CHECK-NEXT: add.8h - %tmp1 = load <8 x i16>, ptr %A - %tmp2 = load <8 x i16>, ptr %B - %tmp3 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> - %tmp4 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> - %tmp5 = add <8 x i16> %tmp3, %tmp4 - ret <8 x i16> %tmp5 +define <8 x i16> @vuzpQi16_undef1(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vuzpQi16_undef1: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1.8h v2, v0, v1 +; CHECK-NEXT: uzp2.8h v0, v0, v1 +; CHECK-NEXT: add.8h v0, v2, v0 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp4 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp5 = add <8 x i16> %tmp3, %tmp4 + ret <8 x i16> %tmp5 +} + +define <8 x i16> @vuzpQi16_undef0(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vuzpQi16_undef0: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI8_0 +; CHECK-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI8_0] +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: uzp2.8h v3, v0, v1 +; CHECK-NEXT: tbl.16b v0, { v0, v1 }, v2 +; CHECK-NEXT: add.8h v0, v0, v3 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp4 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp5 = add <8 x i16> %tmp3, %tmp4 + ret <8 x i16> %tmp5 +} + +define <8 x i16> @vuzpQi16_undef01(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vuzpQi16_undef01: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI9_0 +; CHECK-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI9_0] +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: uzp2.8h v3, v0, v1 +; CHECK-NEXT: tbl.16b v0, { v0, v1 }, v2 +; CHECK-NEXT: add.8h v0, v0, v3 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp4 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp5 = add <8 x i16> %tmp3, %tmp4 + ret <8 x i16> %tmp5 +} + +define <8 x i16> @vuzpQi16_undef012(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vuzpQi16_undef012: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI10_0 +; CHECK-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI10_0] +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: uzp2.8h v3, v0, v1 +; CHECK-NEXT: tbl.16b v0, { v0, v1 }, v2 +; CHECK-NEXT: add.8h v0, v0, v3 +; CHECK-NEXT: ret + %tmp3 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp4 = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + %tmp5 = add <8 x i16> %tmp3, %tmp4 + ret <8 x i16> %tmp5 } diff --git a/llvm/test/CodeGen/AArch64/arm64-zip.ll b/llvm/test/CodeGen/AArch64/arm64-zip.ll index c707265c06c5..349751dda461 100644 --- a/llvm/test/CodeGen/AArch64/arm64-zip.ll +++ b/llvm/test/CodeGen/AArch64/arm64-zip.ll @@ -139,6 +139,90 @@ define <16 x i8> @vzipQi8_undef(ptr %A, ptr %B) nounwind { ret <16 x i8> %tmp5 } +define <8 x i16> @vzip1_undef_01(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip1_undef_01: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI8_0 +; CHECK-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI8_0] +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: tbl.16b v0, { v0, v1 }, v2 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip1_undef_0(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip1_undef_0: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI9_0 +; CHECK-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI9_0] +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: tbl.16b v0, { v0, v1 }, v2 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip1_undef_1(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip1_undef_1: +; CHECK: // %bb.0: +; CHECK-NEXT: zip1.8h v0, v0, v1 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip1_undef_012(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip1_undef_012: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, .LCPI11_0 +; CHECK-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI11_0] +; CHECK-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-NEXT: tbl.16b v0, { v0, v1 }, v2 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip2_undef_01(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip2_undef_01: +; CHECK: // %bb.0: +; CHECK-NEXT: zip2.8h v0, v0, v1 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip2_undef_0(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip2_undef_0: +; CHECK: // %bb.0: +; CHECK-NEXT: zip2.8h v0, v0, v1 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip2_undef_1(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip2_undef_1: +; CHECK: // %bb.0: +; CHECK-NEXT: zip2.8h v0, v0, v1 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + +define <8 x i16> @vzip2_undef_012(<8 x i16> %A, <8 x i16> %B) nounwind { +; CHECK-LABEL: vzip2_undef_012: +; CHECK: // %bb.0: +; CHECK-NEXT: zip2.8h v0, v0, v1 +; CHECK-NEXT: ret + %s = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> + ret <8 x i16> %s +} + define <16 x i8> @combine_v16i8(<8 x i8> %0, <8 x i8> %1) { ; CHECK-LABEL: combine_v16i8: ; CHECK: // %bb.0: @@ -251,9 +335,9 @@ define <16 x i8> @combine_v8i16_8first(<8 x i8> %0, <8 x i8> %1) { ; CHECK-LABEL: combine_v8i16_8first: ; CHECK: // %bb.0: ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1_q2 -; CHECK-NEXT: adrp x8, .LCPI17_0 +; CHECK-NEXT: adrp x8, .LCPI25_0 ; CHECK-NEXT: fmov d2, d0 -; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI17_0] +; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI25_0] ; CHECK-NEXT: tbl.16b v0, { v1, v2 }, v3 ; CHECK-NEXT: ret %3 = shufflevector <8 x i8> %1, <8 x i8> %0, <16 x i32> @@ -266,9 +350,9 @@ define <16 x i8> @combine_v8i16_8firstundef(<8 x i8> %0, <8 x i8> %1) { ; CHECK-LABEL: combine_v8i16_8firstundef: ; CHECK: // %bb.0: ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1_q2 -; CHECK-NEXT: adrp x8, .LCPI18_0 +; CHECK-NEXT: adrp x8, .LCPI26_0 ; CHECK-NEXT: fmov d2, d0 -; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI18_0] +; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI26_0] ; CHECK-NEXT: tbl.16b v0, { v1, v2 }, v3 ; CHECK-NEXT: ret %3 = shufflevector <8 x i8> %1, <8 x i8> %0, <16 x i32> -- GitLab From 3fbaad5a0c67d0a04739ccf51c180c7d829200a7 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 22 Apr 2024 08:57:15 +0100 Subject: [PATCH 120/357] [VectorCombine] Add test coverage for #89390 --- .../VectorCombine/X86/shuffle-of-binops.ll | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll index e2ff343944cf..6412d6dbf701 100644 --- a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll +++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll @@ -199,6 +199,23 @@ define <16 x i16> @shuf_and_v16i16_yy_expensive_shuf(<16 x i16> %x, <16 x i16> % %r = shufflevector <16 x i16> %b0, <16 x i16> %b1, <16 x i32> ret <16 x i16> %r } + +; TODO: negative test - don't fold shuffle(divrem(x,y),divrem(z,w)) if mask contains poison (PR89390) + +define <4 x i32> @shuf_srem_v4i32_poison(<4 x i32> %a0, <4 x i32> %a1) { +; CHECK-LABEL: define <4 x i32> @shuf_srem_v4i32_poison( +; CHECK-SAME: <4 x i32> [[A0:%.*]], <4 x i32> [[A1:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[A1]], <4 x i32> , <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[A0]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[R:%.*]] = srem <4 x i32> [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret <4 x i32> [[R]] +; + %srem0 = srem <4 x i32> %a1, %a0 + %srem1 = srem <4 x i32> , %a0 + %r = shufflevector <4 x i32> %srem0, <4 x i32> %srem1, <4 x i32> + ret <4 x i32> %r +} + ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; AVX: {{.*}} ; SSE: {{.*}} -- GitLab From 4cc9c6d98dfef90d1ffa69977d13ffa2894a10f7 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 22 Apr 2024 09:00:20 +0100 Subject: [PATCH 121/357] [VectorCombine] foldShuffleOfBinops - don't fold shuffle(divrem(x,y),divrem(z,w)) if mask contains poison Fixes #89390 --- llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 5 +++++ .../Transforms/VectorCombine/X86/shuffle-of-binops.ll | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 4918cee1fa82..f23b10540338 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1405,6 +1405,11 @@ bool VectorCombine::foldShuffleOfBinops(Instruction &I) { B0->getOpcode() != B1->getOpcode() || B0->getType() != VecTy) return false; + // Don't introduce poison into div/rem. + if (any_of(Mask, [](int M) { return M == PoisonMaskElem; }) && + B0->isIntDivRem()) + return false; + // Try to replace a binop with a shuffle if the shuffle is not costly. // The new shuffle will choose from a single, common operand, so it may be // cheaper than the existing two-operand shuffle. diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll index 6412d6dbf701..5c4ad4f1fcc4 100644 --- a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll +++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-binops.ll @@ -200,14 +200,14 @@ define <16 x i16> @shuf_and_v16i16_yy_expensive_shuf(<16 x i16> %x, <16 x i16> % ret <16 x i16> %r } -; TODO: negative test - don't fold shuffle(divrem(x,y),divrem(z,w)) if mask contains poison (PR89390) +; negative test - don't fold shuffle(divrem(x,y),divrem(z,w)) if mask contains poison (PR89390) define <4 x i32> @shuf_srem_v4i32_poison(<4 x i32> %a0, <4 x i32> %a1) { ; CHECK-LABEL: define <4 x i32> @shuf_srem_v4i32_poison( ; CHECK-SAME: <4 x i32> [[A0:%.*]], <4 x i32> [[A1:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[A1]], <4 x i32> , <4 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[A0]], <4 x i32> poison, <4 x i32> -; CHECK-NEXT: [[R:%.*]] = srem <4 x i32> [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[SREM0:%.*]] = srem <4 x i32> [[A1]], [[A0]] +; CHECK-NEXT: [[SREM1:%.*]] = srem <4 x i32> , [[A0]] +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[SREM0]], <4 x i32> [[SREM1]], <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[R]] ; %srem0 = srem <4 x i32> %a1, %a0 -- GitLab From eef5798844a6ed489c28b37113f3bcaafd1d6e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Fri, 19 Apr 2024 19:19:06 +0200 Subject: [PATCH 122/357] [clang][Interp] Create full type info for dummy pointers --- clang/lib/AST/Interp/Descriptor.cpp | 8 ----- clang/lib/AST/Interp/Descriptor.h | 6 ++-- clang/lib/AST/Interp/Interp.h | 36 ++++++++------------- clang/lib/AST/Interp/Pointer.cpp | 3 +- clang/lib/AST/Interp/Program.cpp | 21 ++++++------ clang/test/AST/Interp/builtin-align-cxx.cpp | 15 +-------- clang/test/AST/Interp/c.c | 4 +++ 7 files changed, 36 insertions(+), 57 deletions(-) diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index a4ccc0236d29..6704444fccdd 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -309,14 +309,6 @@ Descriptor::Descriptor(const DeclTy &D) assert(Source && "Missing source"); } -/// Dummy array. -Descriptor::Descriptor(const DeclTy &D, UnknownSize) - : Source(D), ElemSize(1), Size(UnknownSizeMark), MDSize(0), - AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false), - IsTemporary(false), IsArray(true), IsDummy(true) { - assert(Source && "Missing source"); -} - QualType Descriptor::getType() const { if (auto *E = asExpr()) return E->getType(); diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/Interp/Descriptor.h index c386fc8ac7b0..f8a574c9b3a0 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/Interp/Descriptor.h @@ -125,7 +125,7 @@ public: /// Flag indicating if the block is an array. const bool IsArray = false; /// Flag indicating if this is a dummy descriptor. - const bool IsDummy = false; + bool IsDummy = false; /// Storage management methods. const BlockCtorFn CtorFn = nullptr; @@ -159,8 +159,8 @@ public: /// Allocates a dummy descriptor. Descriptor(const DeclTy &D); - /// Allocates a dummy array descriptor. - Descriptor(const DeclTy &D, UnknownSize); + /// Make this descriptor a dummy descriptor. + void makeDummy() { IsDummy = true; } QualType getType() const; QualType getElemQualType() const; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index cebedf59e059..813bd02030cb 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -823,9 +823,9 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) { // element in the same array are NOT equal. They have the same Base value, // but a different Offset. This is a pretty rare case, so we fix this here // by comparing pointers to the first elements. - if (!LHS.isZero() && !LHS.isDummy() && LHS.isArrayRoot()) + if (!LHS.isZero() && LHS.isArrayRoot()) VL = LHS.atIndex(0).getByteOffset(); - if (!RHS.isZero() && !RHS.isDummy() && RHS.isArrayRoot()) + if (!RHS.isZero() && RHS.isArrayRoot()) VR = RHS.atIndex(0).getByteOffset(); S.Stk.push(BoolT::from(Fn(Compare(VL, VR)))); @@ -1241,14 +1241,16 @@ inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) { !CheckNull(S, OpPC, Ptr, CSK_Field)) return false; - if (CheckDummy(S, OpPC, Ptr)) { - if (!CheckExtern(S, OpPC, Ptr)) - return false; - if (!CheckRange(S, OpPC, Ptr, CSK_Field)) - return false; - if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) - return false; - } + if (!CheckExtern(S, OpPC, Ptr)) + return false; + if (!CheckRange(S, OpPC, Ptr, CSK_Field)) + return false; + if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) + return false; + + if (Ptr.isBlockPointer() && Off > Ptr.block()->getSize()) + return false; + S.Stk.push(Ptr.atField(Off)); return true; } @@ -1992,11 +1994,6 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { if (!Ptr.isZero()) { if (!CheckArray(S, OpPC, Ptr)) return false; - - if (Ptr.isDummy()) { - S.Stk.push(Ptr); - return true; - } } if (!OffsetHelper(S, OpPC, Offset, Ptr)) @@ -2013,11 +2010,6 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { if (!Ptr.isZero()) { if (!CheckArray(S, OpPC, Ptr)) return false; - - if (Ptr.isDummy()) { - S.Stk.push(Ptr); - return true; - } } if (!OffsetHelper(S, OpPC, Offset, Ptr)) @@ -2053,12 +2045,12 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { inline bool ArrayDecay(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - if (Ptr.isZero() || Ptr.isDummy()) { + if (Ptr.isZero()) { S.Stk.push(Ptr); return true; } - if (!Ptr.isUnknownSizeArray()) { + if (!Ptr.isUnknownSizeArray() || Ptr.isDummy()) { S.Stk.push(Ptr.atIndex(0)); return true; } diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 5ef31671ae7b..c7708de8d8c7 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -139,9 +139,10 @@ APValue Pointer::toAPValue() const { else llvm_unreachable("Invalid allocation type"); - if (isDummy() || isUnknownSizeArray() || Desc->asExpr()) + if (isDummy() || isUnknownSizeArray() || Desc->asExpr()) { return APValue(Base, CharUnits::Zero(), Path, /*IsOnePastEnd=*/false, /*IsNullPtr=*/false); + } // TODO: compute the offset into the object. CharUnits Offset = CharUnits::Zero(); diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 2c8c6781b348..f4c004dd0821 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -148,17 +148,20 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { if (auto It = DummyVariables.find(VD); It != DummyVariables.end()) return It->second; - // Create dummy descriptor. - // We create desriptors of 'array of unknown size' if the type is an array - // type _and_ the size isn't known (it's not a ConstantArrayType). If the size - // is known however, we create a regular dummy pointer. Descriptor *Desc; - if (const auto *AT = VD->getType()->getAsArrayTypeUnsafe(); - AT && !isa(AT)) - Desc = allocateDescriptor(VD, Descriptor::UnknownSize{}); + if (std::optional T = Ctx.classify(VD->getType())) + Desc = createDescriptor(VD, *T, std::nullopt, true, false); else + Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true, + false); + if (!Desc) Desc = allocateDescriptor(VD); + assert(Desc); + Desc->makeDummy(); + + assert(Desc->isDummy()); + // Allocate a block for storage. unsigned I = Globals.size(); @@ -314,8 +317,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { for (const FieldDecl *FD : RD->fields()) { // Note that we DO create fields and descriptors // for unnamed bitfields here, even though we later ignore - // them everywhere. That's because so the FieldDecl's - // getFieldIndex() matches. + // them everywhere. That's so the FieldDecl's getFieldIndex() matches. // Reserve space for the field's descriptor and the offset. BaseSize += align(sizeof(InlineDescriptor)); @@ -348,6 +350,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, Descriptor::MetadataSize MDSize, bool IsConst, bool IsTemporary, bool IsMutable, const Expr *Init) { + // Classes and structures. if (const auto *RT = Ty->getAs()) { if (const auto *Record = getOrCreateRecord(RT->getDecl())) diff --git a/clang/test/AST/Interp/builtin-align-cxx.cpp b/clang/test/AST/Interp/builtin-align-cxx.cpp index 62d73dba929b..c4103953df02 100644 --- a/clang/test/AST/Interp/builtin-align-cxx.cpp +++ b/clang/test/AST/Interp/builtin-align-cxx.cpp @@ -2,19 +2,6 @@ // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=expected,both -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=ref,both - -/// This is just a copy of the one from test/SemaCXX/ with some of the -/// diagnostic output adapted. -/// Also, align32array has an initializer now, which means it's not just -/// a dummy pointer for us and we do actually have type information for it. -/// In the future, we need to retain type information for dummy pointers as -/// well, so here is a test that will break once we do that: -namespace { - _Alignas(32) char heh[4]; - static_assert(!__builtin_is_aligned(&heh[1], 4), ""); // expected-error {{failed}} -} - - // Check that we don't crash when using dependent types in __builtin_align: template void *c(void *d) { // both-note{{candidate template ignored}} @@ -177,7 +164,7 @@ static_assert(wrap_align_up(static_cast(1), const_value(1 << 21)), ""); // // both-note@-1{{in instantiation of function template specialization 'wrap_align_up' requested here}} // Check constant evaluation for pointers: -_Alignas(32) char align32array[128] = {}; +_Alignas(32) char align32array[128]; static_assert(&align32array[0] == &align32array[0], ""); // __builtin_align_up/down can be constant evaluated as a no-op for values // that are known to have greater alignment: diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 5ae9b1dc7bff..db6739e8b19c 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -257,3 +257,7 @@ int Y __attribute__((annotate( 42, (struct TestStruct) { .a = 1, .b = 2 } ))); + +/// This tests that we have full type info, even for values we cannot read. +int dummyarray[5]; +_Static_assert(&dummyarray[0] < &dummyarray[1], ""); // pedantic-warning {{GNU extension}} -- GitLab From 57c24eb0a7482ca7f661a2a9cb45249f1553d6d2 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 22 Apr 2024 09:46:16 +0200 Subject: [PATCH 123/357] Reland "[clang] CTAD: Fix require-clause is not transformed." (#89476) This relands the c8e65e193d542464421ad4f9a9965d45b302ac0c, which was reverted in b48ea2d394911efcc56880fde58f806282db1e8a due to the breakage of windows builtbot. The reland contains some adjustments in the lit test deduction-gudie.cpp, to make the checking text less strict. --- clang/lib/Sema/SemaTemplate.cpp | 27 ++++++++++--------- clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 +--- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 18 +++++++++++++ clang/test/SemaTemplate/deduction-guide.cpp | 28 ++++++++++++++++++++ 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d4976f9d0d11..4bda31ba67c0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2962,19 +2962,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getCanonicalTemplateArgument( Context.getInjectedTemplateArg(NewParam)); } - // Substitute new template parameters into requires-clause if present. - Expr *RequiresClause = - transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); - // FIXME: implement the is_deducible constraint per C++ - // [over.match.class.deduct]p3.3: - // ... and a constraint that is satisfied if and only if the arguments - // of A are deducible (see below) from the return type. - auto *FPrimeTemplateParamList = TemplateParameterList::Create( - Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), - AliasTemplate->getTemplateParameters()->getLAngleLoc(), - FPrimeTemplateParams, - AliasTemplate->getTemplateParameters()->getRAngleLoc(), - /*RequiresClause=*/RequiresClause); // To form a deduction guide f' from f, we leverage clang's instantiation // mechanism, we construct a template argument list where the template @@ -3020,6 +3007,20 @@ void DeclareImplicitDeductionGuidesForTypeAlias( F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), Sema::CodeSynthesisContext::BuildingDeductionGuides)) { auto *GG = cast(FPrime); + // Substitute new template parameters into requires-clause if present. + Expr *RequiresClause = + transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); + // FIXME: implement the is_deducible constraint per C++ + // [over.match.class.deduct]p3.3: + // ... and a constraint that is satisfied if and only if the arguments + // of A are deducible (see below) from the return type. + auto *FPrimeTemplateParamList = TemplateParameterList::Create( + Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), + AliasTemplate->getTemplateParameters()->getLAngleLoc(), + FPrimeTemplateParams, + AliasTemplate->getTemplateParameters()->getRAngleLoc(), + /*RequiresClause=*/RequiresClause); + buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList, GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), GG->getTypeSourceInfo(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3e6676f21c9b..98d5c7cb3a8a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2502,10 +2502,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, assert(Arg.getKind() == TemplateArgument::Type && "unexpected nontype template argument kind in template rewrite"); QualType NewT = Arg.getAsType(); - assert(isa(NewT) && - "type parm not rewritten to type parm"); - auto NewTL = TLB.push(NewT); - NewTL.setNameLoc(TL.getNameLoc()); + TLB.pushTrivial(SemaRef.Context, NewT, TL.getNameLoc()); return NewT; } diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 6f04264a655a..508a3a5da76a 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -289,3 +289,21 @@ using String = Array; // Verify no crash on constructing the aggregate deduction guides. String s("hello"); } // namespace test21 + +// GH89013 +namespace test22 { +class Base {}; +template +class Derived final : public Base {}; + +template +requires __is_base_of(Base, D) +struct Foo { + explicit Foo(D) {} +}; + +template +using AFoo = Foo>; + +AFoo a(Derived{}); +} // namespace test22 diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 58f08aa1eed6..ff5e39216762 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -260,3 +260,31 @@ AG ag = {1}; // CHECK: |-TemplateArgument type 'int' // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' + +template +requires (sizeof(D) == 4) +struct Foo { + Foo(D); +}; + +template +using AFoo = Foo>; +// Verify that the require-clause from the Foo deduction guide is transformed. +// The D occurrence should be rewritten to G. +// +// CHECK-LABEL: Dumping +// CHECK: FunctionTemplateDecl {{.*}} implicit +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 U +// CHECK-NEXT: |-ParenExpr {{.*}} 'bool' +// CHECK-NEXT: | `-BinaryOperator {{.*}} 'bool' '==' +// CHECK-NEXT: | |-UnaryExprOrTypeTraitExpr {{.*}} 'G' +// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} +// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (G) -> Foo>' +// CHECK-NEXT: | `-ParmVarDecl {{.*}} 'G' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (G) -> Foo>' implicit_instantiation +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.*}} 'int' +// CHECK-NEXT: `-ParmVarDecl {{.*}} 'G' + +AFoo aa(G{}); -- GitLab From 57b267905110967860f35a3e97caf3260c681e6d Mon Sep 17 00:00:00 2001 From: Christian Sigg Date: Mon, 22 Apr 2024 10:05:37 +0200 Subject: [PATCH 124/357] Mark `mlir::Value::isa/dyn_cast/cast/...` member functions deprecated. (#89238) See https://mlir.llvm.org/deprecation and https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443/4 --- flang/lib/Optimizer/Analysis/AliasAnalysis.cpp | 2 +- flang/lib/Optimizer/Dialect/FIROps.cpp | 4 ++-- flang/lib/Optimizer/Transforms/AffinePromotion.cpp | 4 ++-- flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp | 4 ++-- mlir/include/mlir/IR/Value.h | 6 +++++- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index e144640081cb..c403b9effbfa 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -29,7 +29,7 @@ using namespace mlir; //===----------------------------------------------------------------------===// static bool isDummyArgument(mlir::Value v) { - auto blockArg{v.dyn_cast()}; + auto blockArg{mlir::dyn_cast(v)}; if (!blockArg) return false; diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 5c24c95db427..cc08f29a98f0 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -2165,7 +2165,7 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser, } fir::DoLoopOp fir::getForInductionVarOwner(mlir::Value val) { - auto ivArg = val.dyn_cast(); + auto ivArg = mlir::dyn_cast(val); if (!ivArg) return {}; assert(ivArg.getOwner() && "unlinked block argument"); @@ -3777,7 +3777,7 @@ valueCheckFirAttributes(mlir::Value value, if (auto loadOp = mlir::dyn_cast(definingOp)) value = loadOp.getMemref(); // If this is a function argument, look in the argument attributes. - if (auto blockArg = value.dyn_cast()) { + if (auto blockArg = mlir::dyn_cast(value)) { if (blockArg.getOwner() && blockArg.getOwner()->isEntryBlock()) if (auto funcOp = mlir::dyn_cast( blockArg.getOwner()->getParentOp())) diff --git a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp index d1831cf1c200..64531cb1868e 100644 --- a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp +++ b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp @@ -63,7 +63,7 @@ struct AffineFunctionAnalysis { } // namespace static bool analyzeCoordinate(mlir::Value coordinate, mlir::Operation *op) { - if (auto blockArg = coordinate.dyn_cast()) { + if (auto blockArg = mlir::dyn_cast(coordinate)) { if (isa(blockArg.getOwner()->getParentOp())) return true; LLVM_DEBUG(llvm::dbgs() << "AffineLoopAnalysis: array coordinate is not a " @@ -224,7 +224,7 @@ private: if (auto op = value.getDefiningOp()) if (auto intConstant = op.getValue().dyn_cast()) return toAffineExpr(intConstant.getInt()); - if (auto blockArg = value.dyn_cast()) { + if (auto blockArg = mlir::dyn_cast(value)) { affineArgs.push_back(value); if (isa(blockArg.getOwner()->getParentOp()) || isa(blockArg.getOwner()->getParentOp())) diff --git a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp index 18ca5711bfea..a08d58383d3a 100644 --- a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp +++ b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp @@ -187,7 +187,7 @@ public: LLVM_DEBUG(llvm::dbgs() << "popset: " << *op << '\n'); auto popFn = [&](auto rop) { assert(val && "op must have a result value"); - auto resNum = val.cast().getResultNumber(); + auto resNum = mlir::cast(val).getResultNumber(); llvm::SmallVector results; rop.resultToSourceOps(results, resNum); for (auto u : results) @@ -296,7 +296,7 @@ public: visited.insert(val); // Process a block argument. - if (auto ba = val.dyn_cast()) { + if (auto ba = mlir::dyn_cast(val)) { collectArrayMentionFrom(ba); return; } diff --git a/mlir/include/mlir/IR/Value.h b/mlir/include/mlir/IR/Value.h index a74d0faa1dfc..cdbc6cc37436 100644 --- a/mlir/include/mlir/IR/Value.h +++ b/mlir/include/mlir/IR/Value.h @@ -98,21 +98,25 @@ public: constexpr Value(detail::ValueImpl *impl = nullptr) : impl(impl) {} template + [[deprecated("Use isa() instead")]] bool isa() const { return llvm::isa(*this); } template + [[deprecated("Use dyn_cast() instead")]] U dyn_cast() const { return llvm::dyn_cast(*this); } template + [[deprecated("Use dyn_cast_or_null() instead")]] U dyn_cast_or_null() const { - return llvm::dyn_cast_if_present(*this); + return llvm::dyn_cast_or_null(*this); } template + [[deprecated("Use cast() instead")]] U cast() const { return llvm::cast(*this); } -- GitLab From dc9664a8adae17f2083fbcc8e96cfce606c56d57 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 22 Apr 2024 10:13:04 +0200 Subject: [PATCH 125/357] CodeGen: Strengthen definition of F{MIN|MAX}NUM_IEEE nodes (#85195) Previously these were declared as having the 2008 behavior, with underspecified signed zero handling. Currently, AMDGPU, PPC and LoongArch mark these as legal. The AMDGPU and PPC instructions respect the signed zero behavior. The LoongArch documentation doesn't state, but I'm assuming it also does. --- llvm/docs/GlobalISel/GenericOpcode.rst | 28 +++++++++++++++++----- llvm/include/llvm/CodeGen/ISDOpcodes.h | 14 +++++++---- llvm/include/llvm/Target/GenericOpcodes.td | 15 ++++++++---- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index a12627c01d20..492d30280f47 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -521,16 +521,32 @@ The return value of (FMAXNUM 0.0, -0.0) could be either 0.0 or -0.0. G_FMINNUM_IEEE ^^^^^^^^^^^^^^ -Perform floating-point minimum on two values, following the IEEE-754 2008 -definition. This differs from FMINNUM in the handling of signaling NaNs. If one -input is a signaling NaN, returns a quiet NaN. +Perform floating-point minimum on two values, following IEEE-754 +definitions. This differs from FMINNUM in the handling of signaling +NaNs. + +If one input is a signaling NaN, returns a quiet NaN. This matches +IEEE-754 2008's minnum/maxnum for signaling NaNs (which differs from +2019). + +These treat -0 as ordered less than +0, matching the behavior of +IEEE-754 2019's minimumNumber/maximumNumber (which was unspecified in +2008). G_FMAXNUM_IEEE ^^^^^^^^^^^^^^ -Perform floating-point maximum on two values, following the IEEE-754 2008 -definition. This differs from FMAXNUM in the handling of signaling NaNs. If one -input is a signaling NaN, returns a quiet NaN. +Perform floating-point maximum on two values, following IEEE-754 +definitions. This differs from FMAXNUM in the handling of signaling +NaNs. + +If one input is a signaling NaN, returns a quiet NaN. This matches +IEEE-754 2008's minnum/maxnum for signaling NaNs (which differs from +2019). + +These treat -0 as ordered less than +0, matching the behavior of +IEEE-754 2019's minimumNumber/maximumNumber (which was unspecified in +2008). G_FMINIMUM ^^^^^^^^^^ diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h index 49d51a27e3c0..078a936b061a 100644 --- a/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -971,10 +971,16 @@ enum NodeType { FMINNUM, FMAXNUM, - /// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on - /// two values, following the IEEE-754 2008 definition. This differs from - /// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a - /// signaling NaN, returns a quiet NaN. + /// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or + /// maximumNumber on two values, following IEEE-754 definitions. This differs + /// from FMINNUM/FMAXNUM in the handling of signaling NaNs, and signed zero. + /// + /// If one input is a signaling NaN, returns a quiet NaN. This matches + /// IEEE-754 2008's minnum/maxnum behavior for signaling NaNs (which differs + /// from 2019). + /// + /// These treat -0 as ordered less than +0, matching the behavior of IEEE-754 + /// 2019's minimumNumber/maximumNumber. FMINNUM_IEEE, FMAXNUM_IEEE, diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index e8cf8fcb647f..8380d2738d16 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -795,10 +795,17 @@ def G_FMAXNUM : GenericInstruction { let isCommutable = true; } -// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on -// two values, following the IEEE-754 2008 definition. This differs from -// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a -// signaling NaN, returns a quiet NaN. +// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or +// maximumNumber on two values, following IEEE-754 definitions. This +// differs from FMINNUM/FMAXNUM in the handling of signaling NaNs, and +// signed zero. +// +// If one input is a signaling NaN, returns a quiet NaN. This matches +// IEEE-754 2008's minnum/maxnum behavior for signaling NaNs (which +// differs from 2019). +// +// These treat -0 as ordered less than +0, matching the behavior of +// IEEE-754 2019's minimumNumber/maximumNumber. def G_FMINNUM_IEEE : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins type0:$src1, type0:$src2); -- GitLab From 8b2e50bdda3c7cf68268ef23e9cc532797743511 Mon Sep 17 00:00:00 2001 From: Christian Sigg Date: Mon, 22 Apr 2024 10:12:57 +0200 Subject: [PATCH 126/357] [llvm][bazel] Fix BUILD after e86ebe4ff8705ef30b332e2104ed1c84fc729966. --- utils/bazel/llvm-project-overlay/llvm/BUILD.bazel | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index af9dc26abec4..c9c0edb1dc31 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -4607,11 +4607,16 @@ cc_binary( copts = llvm_copts, stamp = 0, deps = [ + ":AllTargetsAsmParsers", + ":AllTargetsCodeGens", ":BitWriter", ":Core", ":IRPrinter", ":IRReader", + ":MC", ":Support", + ":Target", + ":TargetParser", ":TransformUtils", ], ) -- GitLab From adb25477fb41dc42fc1abef75039dd7b60c05206 Mon Sep 17 00:00:00 2001 From: pvanhout Date: Mon, 22 Apr 2024 10:18:06 +0200 Subject: [PATCH 127/357] [llvm-split] Add missing TargetParser dependency --- llvm/tools/llvm-split/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/tools/llvm-split/CMakeLists.txt b/llvm/tools/llvm-split/CMakeLists.txt index 0579298462d1..1104e3145952 100644 --- a/llvm/tools/llvm-split/CMakeLists.txt +++ b/llvm/tools/llvm-split/CMakeLists.txt @@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS MC Support Target + TargetParser ) add_llvm_tool(llvm-split -- GitLab From 6195e228eb2a7085fac53603f534d2401ab1ac39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 10:32:31 +0200 Subject: [PATCH 128/357] Revert "[clang][Interp] Create full type info for dummy pointers" This reverts commit eef5798844a6ed489c28b37113f3bcaafd1d6e68. This breaks two tests on an arm builder: https://lab.llvm.org/buildbot/#/builders/245/builds/23496 --- clang/lib/AST/Interp/Descriptor.cpp | 8 +++++ clang/lib/AST/Interp/Descriptor.h | 6 ++-- clang/lib/AST/Interp/Interp.h | 36 +++++++++++++-------- clang/lib/AST/Interp/Pointer.cpp | 3 +- clang/lib/AST/Interp/Program.cpp | 21 ++++++------ clang/test/AST/Interp/builtin-align-cxx.cpp | 15 ++++++++- clang/test/AST/Interp/c.c | 4 --- 7 files changed, 57 insertions(+), 36 deletions(-) diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index 6704444fccdd..a4ccc0236d29 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -309,6 +309,14 @@ Descriptor::Descriptor(const DeclTy &D) assert(Source && "Missing source"); } +/// Dummy array. +Descriptor::Descriptor(const DeclTy &D, UnknownSize) + : Source(D), ElemSize(1), Size(UnknownSizeMark), MDSize(0), + AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false), + IsTemporary(false), IsArray(true), IsDummy(true) { + assert(Source && "Missing source"); +} + QualType Descriptor::getType() const { if (auto *E = asExpr()) return E->getType(); diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/Interp/Descriptor.h index f8a574c9b3a0..c386fc8ac7b0 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/Interp/Descriptor.h @@ -125,7 +125,7 @@ public: /// Flag indicating if the block is an array. const bool IsArray = false; /// Flag indicating if this is a dummy descriptor. - bool IsDummy = false; + const bool IsDummy = false; /// Storage management methods. const BlockCtorFn CtorFn = nullptr; @@ -159,8 +159,8 @@ public: /// Allocates a dummy descriptor. Descriptor(const DeclTy &D); - /// Make this descriptor a dummy descriptor. - void makeDummy() { IsDummy = true; } + /// Allocates a dummy array descriptor. + Descriptor(const DeclTy &D, UnknownSize); QualType getType() const; QualType getElemQualType() const; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 813bd02030cb..cebedf59e059 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -823,9 +823,9 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) { // element in the same array are NOT equal. They have the same Base value, // but a different Offset. This is a pretty rare case, so we fix this here // by comparing pointers to the first elements. - if (!LHS.isZero() && LHS.isArrayRoot()) + if (!LHS.isZero() && !LHS.isDummy() && LHS.isArrayRoot()) VL = LHS.atIndex(0).getByteOffset(); - if (!RHS.isZero() && RHS.isArrayRoot()) + if (!RHS.isZero() && !RHS.isDummy() && RHS.isArrayRoot()) VR = RHS.atIndex(0).getByteOffset(); S.Stk.push(BoolT::from(Fn(Compare(VL, VR)))); @@ -1241,16 +1241,14 @@ inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) { !CheckNull(S, OpPC, Ptr, CSK_Field)) return false; - if (!CheckExtern(S, OpPC, Ptr)) - return false; - if (!CheckRange(S, OpPC, Ptr, CSK_Field)) - return false; - if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) - return false; - - if (Ptr.isBlockPointer() && Off > Ptr.block()->getSize()) - return false; - + if (CheckDummy(S, OpPC, Ptr)) { + if (!CheckExtern(S, OpPC, Ptr)) + return false; + if (!CheckRange(S, OpPC, Ptr, CSK_Field)) + return false; + if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) + return false; + } S.Stk.push(Ptr.atField(Off)); return true; } @@ -1994,6 +1992,11 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { if (!Ptr.isZero()) { if (!CheckArray(S, OpPC, Ptr)) return false; + + if (Ptr.isDummy()) { + S.Stk.push(Ptr); + return true; + } } if (!OffsetHelper(S, OpPC, Offset, Ptr)) @@ -2010,6 +2013,11 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { if (!Ptr.isZero()) { if (!CheckArray(S, OpPC, Ptr)) return false; + + if (Ptr.isDummy()) { + S.Stk.push(Ptr); + return true; + } } if (!OffsetHelper(S, OpPC, Offset, Ptr)) @@ -2045,12 +2053,12 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { inline bool ArrayDecay(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - if (Ptr.isZero()) { + if (Ptr.isZero() || Ptr.isDummy()) { S.Stk.push(Ptr); return true; } - if (!Ptr.isUnknownSizeArray() || Ptr.isDummy()) { + if (!Ptr.isUnknownSizeArray()) { S.Stk.push(Ptr.atIndex(0)); return true; } diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index c7708de8d8c7..5ef31671ae7b 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -139,10 +139,9 @@ APValue Pointer::toAPValue() const { else llvm_unreachable("Invalid allocation type"); - if (isDummy() || isUnknownSizeArray() || Desc->asExpr()) { + if (isDummy() || isUnknownSizeArray() || Desc->asExpr()) return APValue(Base, CharUnits::Zero(), Path, /*IsOnePastEnd=*/false, /*IsNullPtr=*/false); - } // TODO: compute the offset into the object. CharUnits Offset = CharUnits::Zero(); diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index f4c004dd0821..2c8c6781b348 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -148,20 +148,17 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { if (auto It = DummyVariables.find(VD); It != DummyVariables.end()) return It->second; + // Create dummy descriptor. + // We create desriptors of 'array of unknown size' if the type is an array + // type _and_ the size isn't known (it's not a ConstantArrayType). If the size + // is known however, we create a regular dummy pointer. Descriptor *Desc; - if (std::optional T = Ctx.classify(VD->getType())) - Desc = createDescriptor(VD, *T, std::nullopt, true, false); + if (const auto *AT = VD->getType()->getAsArrayTypeUnsafe(); + AT && !isa(AT)) + Desc = allocateDescriptor(VD, Descriptor::UnknownSize{}); else - Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true, - false); - if (!Desc) Desc = allocateDescriptor(VD); - assert(Desc); - Desc->makeDummy(); - - assert(Desc->isDummy()); - // Allocate a block for storage. unsigned I = Globals.size(); @@ -317,7 +314,8 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { for (const FieldDecl *FD : RD->fields()) { // Note that we DO create fields and descriptors // for unnamed bitfields here, even though we later ignore - // them everywhere. That's so the FieldDecl's getFieldIndex() matches. + // them everywhere. That's because so the FieldDecl's + // getFieldIndex() matches. // Reserve space for the field's descriptor and the offset. BaseSize += align(sizeof(InlineDescriptor)); @@ -350,7 +348,6 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, Descriptor::MetadataSize MDSize, bool IsConst, bool IsTemporary, bool IsMutable, const Expr *Init) { - // Classes and structures. if (const auto *RT = Ty->getAs()) { if (const auto *Record = getOrCreateRecord(RT->getDecl())) diff --git a/clang/test/AST/Interp/builtin-align-cxx.cpp b/clang/test/AST/Interp/builtin-align-cxx.cpp index c4103953df02..62d73dba929b 100644 --- a/clang/test/AST/Interp/builtin-align-cxx.cpp +++ b/clang/test/AST/Interp/builtin-align-cxx.cpp @@ -2,6 +2,19 @@ // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=expected,both -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=ref,both + +/// This is just a copy of the one from test/SemaCXX/ with some of the +/// diagnostic output adapted. +/// Also, align32array has an initializer now, which means it's not just +/// a dummy pointer for us and we do actually have type information for it. +/// In the future, we need to retain type information for dummy pointers as +/// well, so here is a test that will break once we do that: +namespace { + _Alignas(32) char heh[4]; + static_assert(!__builtin_is_aligned(&heh[1], 4), ""); // expected-error {{failed}} +} + + // Check that we don't crash when using dependent types in __builtin_align: template void *c(void *d) { // both-note{{candidate template ignored}} @@ -164,7 +177,7 @@ static_assert(wrap_align_up(static_cast(1), const_value(1 << 21)), ""); // // both-note@-1{{in instantiation of function template specialization 'wrap_align_up' requested here}} // Check constant evaluation for pointers: -_Alignas(32) char align32array[128]; +_Alignas(32) char align32array[128] = {}; static_assert(&align32array[0] == &align32array[0], ""); // __builtin_align_up/down can be constant evaluated as a no-op for values // that are known to have greater alignment: diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index db6739e8b19c..5ae9b1dc7bff 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -257,7 +257,3 @@ int Y __attribute__((annotate( 42, (struct TestStruct) { .a = 1, .b = 2 } ))); - -/// This tests that we have full type info, even for values we cannot read. -int dummyarray[5]; -_Static_assert(&dummyarray[0] < &dummyarray[1], ""); // pedantic-warning {{GNU extension}} -- GitLab From 0ff992e5f210fdcbfdd1dcc3687c9aeabde318c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 10:16:22 +0200 Subject: [PATCH 129/357] [clang][Interp][NFC] Get ComplexType directly Instead of doing a isa<> + getAs<> --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index f317f506d24f..486ad9db625d 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -922,9 +922,9 @@ bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueIni return true; } - if (QT->isAnyComplexType()) { + if (const auto *ComplexTy = E->getType()->getAs()) { assert(Initializing); - QualType ElemQT = QT->getAs()->getElementType(); + QualType ElemQT = ComplexTy->getElementType(); PrimType ElemT = classifyPrim(ElemQT); for (unsigned I = 0; I < 2; ++I) { if (!this->visitZeroInitializer(ElemT, ElemQT, E)) @@ -1098,13 +1098,13 @@ bool ByteCodeExprGen::VisitInitListExpr(const InitListExpr *E) { return true; } - if (T->isAnyComplexType()) { + if (const auto *ComplexTy = E->getType()->getAs()) { unsigned NumInits = E->getNumInits(); if (NumInits == 1) return this->delegate(E->inits()[0]); - QualType ElemQT = E->getType()->getAs()->getElementType(); + QualType ElemQT = ComplexTy->getElementType(); PrimType ElemT = classifyPrim(ElemQT); if (NumInits == 0) { // Zero-initialize both elements. -- GitLab From 6b6c7e46cc1e97b678e969bad78825dd02c11ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 10:24:41 +0200 Subject: [PATCH 130/357] [clang][Interp][NFC] Test out-of-bounds access on vectors --- clang/test/AST/Interp/vectors.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/Interp/vectors.cpp index 5c4694f122d8..cb8bcd4fdda7 100644 --- a/clang/test/AST/Interp/vectors.cpp +++ b/clang/test/AST/Interp/vectors.cpp @@ -8,6 +8,13 @@ static_assert(A[1] == 2, ""); // ref-error {{not an integral constant expression static_assert(A[2] == 3, ""); // ref-error {{not an integral constant expression}} static_assert(A[3] == 4, ""); // ref-error {{not an integral constant expression}} + +/// FIXME: It would be nice if the note said 'vector' instead of 'array'. +static_assert(A[12] == 4, ""); // ref-error {{not an integral constant expression}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}} + + /// VectorSplat casts typedef __attribute__(( ext_vector_type(4) )) float float4; constexpr float4 vec4_0 = (float4)0.5f; -- GitLab From e614e037f371e92499e19ada730f61e77d640780 Mon Sep 17 00:00:00 2001 From: Fraser Cormack Date: Mon, 22 Apr 2024 09:50:39 +0100 Subject: [PATCH 131/357] [libclc] Fix build with Unix Makefiles (#89147) Commit #87622 broke the build. Ninja was happy with creating the output directories as necessary, but Unix Makefiles isn't. Ensure they are always created. Fixes #88626. --- libclc/cmake/modules/AddLibclc.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake index 5e09cde8035c..bbedc244a728 100644 --- a/libclc/cmake/modules/AddLibclc.cmake +++ b/libclc/cmake/modules/AddLibclc.cmake @@ -39,6 +39,10 @@ function(compile_to_bc) set( TARGET_ARG "-target" ${ARG_TRIPLE} ) endif() + # Ensure the directory we are told to output to exists + get_filename_component( ARG_OUTPUT_DIR ${ARG_OUTPUT} DIRECTORY ) + file( MAKE_DIRECTORY ${ARG_OUTPUT_DIR} ) + add_custom_command( OUTPUT ${ARG_OUTPUT}${TMP_SUFFIX} COMMAND libclc::clang -- GitLab From c2d665b7aeb68f3e8e643ee9dfe5bb7dd31137e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 10:30:38 +0200 Subject: [PATCH 132/357] [clang][Interp] Support ImplicitArrayInitExpr for vectors --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 14 ++++++++++++++ clang/test/AST/Interp/vectors.cpp | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 486ad9db625d..5b9ef9980c9c 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -935,6 +935,20 @@ bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueIni return true; } + if (const auto *VecT = E->getType()->getAs()) { + unsigned NumVecElements = VecT->getNumElements(); + QualType ElemQT = VecT->getElementType(); + PrimType ElemT = classifyPrim(ElemQT); + + for (unsigned I = 0; I < NumVecElements; ++I) { + if (!this->visitZeroInitializer(ElemT, ElemQT, E)) + return false; + if (!this->emitInitElem(ElemT, I, E)) + return false; + } + return true; + } + return false; } diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/Interp/vectors.cpp index cb8bcd4fdda7..49dae14fcf64 100644 --- a/clang/test/AST/Interp/vectors.cpp +++ b/clang/test/AST/Interp/vectors.cpp @@ -25,6 +25,19 @@ static_assert(vec4_0[3] == 0.5, ""); // ref-error {{not an integral constant exp constexpr int vec4_0_discarded = ((float4)12.0f, 0); +/// ImplicitValueInitExpr of vector type +constexpr float4 arr4[2] = { + {1,2,3,4}, +}; +static_assert(arr4[0][0] == 1, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[0][1] == 2, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[0][2] == 3, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[0][3] == 4, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} +static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}} + /// From constant-expression-cxx11.cpp namespace Vector { -- GitLab From bfd19445c38a2ad6a1def7ee9a1f8ff26a159caf Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Mon, 22 Apr 2024 10:11:09 +0100 Subject: [PATCH 133/357] [flang] de-duplicate AbstractResult pass (#88867) This is the first proof of concept of the modification of FIR codegen to fully support a variety of top level operations (beyond just func.func) proposed in https://discourse.llvm.org/t/rfc-add-an-interface-for-top-level-container-operations --- .../flang/Optimizer/Transforms/Passes.h | 5 +- .../flang/Optimizer/Transforms/Passes.td | 12 +- flang/include/flang/Tools/CLOptions.inc | 28 ++- .../Optimizer/Transforms/AbstractResult.cpp | 170 +++++++++--------- .../test/Driver/mlir-debug-pass-pipeline.f90 | 8 +- flang/test/Driver/mlir-pass-pipeline.f90 | 8 +- flang/test/Fir/abstract-result-2.fir | 2 +- flang/test/Fir/abstract-results.fir | 8 +- flang/test/Fir/basic-program.fir | 8 +- ...-trivial-procedure-binding-description.f90 | 2 +- 10 files changed, 139 insertions(+), 112 deletions(-) diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index d8840d9e967b..4d290d87d4cc 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -31,8 +31,7 @@ namespace fir { // Passes defined in Passes.td //===----------------------------------------------------------------------===// -#define GEN_PASS_DECL_ABSTRACTRESULTONFUNCOPT -#define GEN_PASS_DECL_ABSTRACTRESULTONGLOBALOPT +#define GEN_PASS_DECL_ABSTRACTRESULTOPT #define GEN_PASS_DECL_AFFINEDIALECTPROMOTION #define GEN_PASS_DECL_AFFINEDIALECTDEMOTION #define GEN_PASS_DECL_ANNOTATECONSTANTOPERANDS @@ -50,8 +49,6 @@ namespace fir { #define GEN_PASS_DECL_OPENACCDATAOPERANDCONVERSION #include "flang/Optimizer/Transforms/Passes.h.inc" -std::unique_ptr createAbstractResultOnFuncOptPass(); -std::unique_ptr createAbstractResultOnGlobalOptPass(); std::unique_ptr createAffineDemotionPass(); std::unique_ptr createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {}); diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index bfc0db8124af..467b7e1c472e 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -16,8 +16,8 @@ include "mlir/Pass/PassBase.td" -class AbstractResultOptBase - : Pass<"abstract-result-on-" # optExt # "-opt", operation> { +def AbstractResultOpt + : Pass<"abstract-result"> { let summary = "Convert fir.array, fir.box and fir.rec function result to " "function argument"; let description = [{ @@ -35,14 +35,6 @@ class AbstractResultOptBase ]; } -def AbstractResultOnFuncOpt : AbstractResultOptBase<"func", "mlir::func::FuncOp"> { - let constructor = "::fir::createAbstractResultOnFuncOptPass()"; -} - -def AbstractResultOnGlobalOpt : AbstractResultOptBase<"global", "fir::GlobalOp"> { - let constructor = "::fir::createAbstractResultOnGlobalOptPass()"; -} - def AffineDialectPromotion : Pass<"promote-to-affine", "::mlir::func::FuncOp"> { let summary = "Promotes `fir.{do_loop,if}` to `affine.{for,if}`."; let description = [{ diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index ea297fb337a2..44ff2b3f70ff 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -19,6 +19,7 @@ #include "flang/Optimizer/Transforms/Passes.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CommandLine.h" +#include #define DisableOption(DOName, DOOption, DODescription) \ static llvm::cl::opt disable##DOName("disable-" DOOption, \ @@ -86,6 +87,29 @@ DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite", DisableOption(ExternalNameConversion, "external-name-interop", "convert names with external convention"); +// TODO: remove once these are used for non-codegen passes +#if !defined(FLANG_EXCLUDE_CODEGEN) +using PassConstructor = std::unique_ptr(); + +template +void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) { + pm.addNestedPass(ctor()); +} + +template > +void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) { + addNestedPassToOps(pm, ctor); + addNestedPassToOps(pm, ctor); +} + +void addNestedPassToAllTopLevelOperations( + mlir::PassManager &pm, PassConstructor ctor) { + addNestedPassToOps(pm, ctor); +} +#endif + /// Generic for adding a pass to the pass manager if it is not disabled. template void addPassConditionally( @@ -304,9 +328,7 @@ inline void createDebugPasses( inline void createDefaultFIRCodeGenPassPipeline( mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config) { fir::addBoxedProcedurePass(pm); - pm.addNestedPass( - fir::createAbstractResultOnFuncOptPass()); - pm.addNestedPass(fir::createAbstractResultOnGlobalOptPass()); + addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt); fir::addCodeGenRewritePass(pm); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm, config.Underscoring); diff --git a/flang/lib/Optimizer/Transforms/AbstractResult.cpp b/flang/lib/Optimizer/Transforms/AbstractResult.cpp index dd1ddd16f2de..eb4dd637bb16 100644 --- a/flang/lib/Optimizer/Transforms/AbstractResult.cpp +++ b/flang/lib/Optimizer/Transforms/AbstractResult.cpp @@ -16,13 +16,12 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Diagnostics.h" #include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" #include "mlir/Transforms/DialectConversion.h" -#include "mlir/Transforms/Passes.h" #include "llvm/ADT/TypeSwitch.h" namespace fir { -#define GEN_PASS_DEF_ABSTRACTRESULTONFUNCOPT -#define GEN_PASS_DEF_ABSTRACTRESULTONGLOBALOPT +#define GEN_PASS_DEF_ABSTRACTRESULTOPT #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir @@ -285,59 +284,12 @@ private: bool shouldBoxResult; }; -/// @brief Base CRTP class for AbstractResult pass family. -/// Contains common logic for abstract result conversion in a reusable fashion. -/// @tparam Pass target class that implements operation-specific logic. -/// @tparam PassBase base class template for the pass generated by TableGen. -/// The `Pass` class must define runOnSpecificOperation(OpTy, bool, -/// mlir::RewritePatternSet&, mlir::ConversionTarget&) member function. -/// This function should implement operation-specific functionality. -template class PassBase> -class AbstractResultOptTemplate : public PassBase { +class AbstractResultOpt + : public fir::impl::AbstractResultOptBase { public: - void runOnOperation() override { - auto *context = &this->getContext(); - auto op = this->getOperation(); - - mlir::RewritePatternSet patterns(context); - mlir::ConversionTarget target = *context; - const bool shouldBoxResult = this->passResultAsBox.getValue(); - - auto &self = static_cast(*this); - self.runOnSpecificOperation(op, shouldBoxResult, patterns, target); - - // Convert the calls and, if needed, the ReturnOp in the function body. - target.addLegalDialect(); - target.addIllegalOp(); - target.addDynamicallyLegalOp([](fir::CallOp call) { - return !hasAbstractResult(call.getFunctionType()); - }); - target.addDynamicallyLegalOp([](fir::AddrOfOp addrOf) { - if (auto funTy = addrOf.getType().dyn_cast()) - return !hasAbstractResult(funTy); - return true; - }); - target.addDynamicallyLegalOp([](fir::DispatchOp dispatch) { - return !hasAbstractResult(dispatch.getFunctionType()); - }); - - patterns.insert>(context, shouldBoxResult); - patterns.insert>(context, shouldBoxResult); - patterns.insert(context); - patterns.insert(context, shouldBoxResult); - if (mlir::failed( - mlir::applyPartialConversion(op, target, std::move(patterns)))) { - mlir::emitError(op.getLoc(), "error in converting abstract results\n"); - this->signalPassFailure(); - } - } -}; + using fir::impl::AbstractResultOptBase< + AbstractResultOpt>::AbstractResultOptBase; -class AbstractResultOnFuncOpt - : public AbstractResultOptTemplate { -public: void runOnSpecificOperation(mlir::func::FuncOp func, bool shouldBoxResult, mlir::RewritePatternSet &patterns, mlir::ConversionTarget &target) { @@ -386,25 +338,20 @@ public: } } } -}; -inline static bool containsFunctionTypeWithAbstractResult(mlir::Type type) { - return mlir::TypeSwitch(type) - .Case([](fir::BoxProcType boxProc) { - return fir::hasAbstractResult( - boxProc.getEleTy().cast()); - }) - .Case([](fir::PointerType pointer) { - return fir::hasAbstractResult( - pointer.getEleTy().cast()); - }) - .Default([](auto &&) { return false; }); -} + inline static bool containsFunctionTypeWithAbstractResult(mlir::Type type) { + return mlir::TypeSwitch(type) + .Case([](fir::BoxProcType boxProc) { + return fir::hasAbstractResult( + boxProc.getEleTy().cast()); + }) + .Case([](fir::PointerType pointer) { + return fir::hasAbstractResult( + pointer.getEleTy().cast()); + }) + .Default([](auto &&) { return false; }); + } -class AbstractResultOnGlobalOpt - : public AbstractResultOptTemplate< - AbstractResultOnGlobalOpt, fir::impl::AbstractResultOnGlobalOptBase> { -public: void runOnSpecificOperation(fir::GlobalOp global, bool, mlir::RewritePatternSet &, mlir::ConversionTarget &) { @@ -412,14 +359,77 @@ public: TODO(global->getLoc(), "support for procedure pointers"); } } -}; -} // end anonymous namespace -} // namespace fir -std::unique_ptr fir::createAbstractResultOnFuncOptPass() { - return std::make_unique(); -} + /// Run the pass on a ModuleOp. This makes fir-opt --abstract-result work. + void runOnModule() { + mlir::ModuleOp mod = mlir::cast(getOperation()); + + auto pass = std::make_unique(); + pass->copyOptionValuesFrom(this); + mlir::OpPassManager pipeline; + pipeline.addPass(std::unique_ptr{pass.release()}); + + // Run the pass on all operations directly nested inside of the ModuleOp + // we can't just call runOnSpecificOperation here because the pass + // implementation only works when scoped to a particular func.func or + // fir.global + for (mlir::Region ®ion : mod->getRegions()) { + for (mlir::Block &block : region.getBlocks()) { + for (mlir::Operation &op : block.getOperations()) { + if (mlir::failed(runPipeline(pipeline, &op))) { + mlir::emitError(op.getLoc(), "Failed to run abstract result pass"); + signalPassFailure(); + return; + } + } + } + } + } -std::unique_ptr fir::createAbstractResultOnGlobalOptPass() { - return std::make_unique(); -} + void runOnOperation() override { + auto *context = &this->getContext(); + mlir::Operation *op = this->getOperation(); + if (mlir::isa(op)) { + runOnModule(); + return; + } + + mlir::RewritePatternSet patterns(context); + mlir::ConversionTarget target = *context; + const bool shouldBoxResult = this->passResultAsBox.getValue(); + + mlir::TypeSwitch(op) + .Case([&](auto op) { + runOnSpecificOperation(op, shouldBoxResult, patterns, target); + }); + + // Convert the calls and, if needed, the ReturnOp in the function body. + target.addLegalDialect(); + target.addIllegalOp(); + target.addDynamicallyLegalOp([](fir::CallOp call) { + return !hasAbstractResult(call.getFunctionType()); + }); + target.addDynamicallyLegalOp([](fir::AddrOfOp addrOf) { + if (auto funTy = addrOf.getType().dyn_cast()) + return !hasAbstractResult(funTy); + return true; + }); + target.addDynamicallyLegalOp([](fir::DispatchOp dispatch) { + return !hasAbstractResult(dispatch.getFunctionType()); + }); + + patterns.insert>(context, shouldBoxResult); + patterns.insert>(context, shouldBoxResult); + patterns.insert(context); + patterns.insert(context, shouldBoxResult); + if (mlir::failed( + mlir::applyPartialConversion(op, target, std::move(patterns)))) { + mlir::emitError(op->getLoc(), "error in converting abstract results\n"); + this->signalPassFailure(); + } + } +}; + +} // end anonymous namespace +} // namespace fir \ No newline at end of file diff --git a/flang/test/Driver/mlir-debug-pass-pipeline.f90 b/flang/test/Driver/mlir-debug-pass-pipeline.f90 index 04d432f854ca..ef84cb80ecf1 100644 --- a/flang/test/Driver/mlir-debug-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-debug-pass-pipeline.f90 @@ -72,11 +72,13 @@ end program ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! ALL-NEXT: BoxedProcedurePass -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction'] ! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOnFuncOpt +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index cfa0de63cde5..d1ff2869b0a6 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -67,11 +67,13 @@ end program ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! ALL-NEXT: BoxedProcedurePass -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction'] ! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOnFuncOpt +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: AbstractResultOpt ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Fir/abstract-result-2.fir b/flang/test/Fir/abstract-result-2.fir index 08b723b83059..af13d57476e8 100644 --- a/flang/test/Fir/abstract-result-2.fir +++ b/flang/test/Fir/abstract-result-2.fir @@ -1,4 +1,4 @@ -// RUN: fir-opt %s --abstract-result-on-func-opt | FileCheck %s +// RUN: fir-opt %s --abstract-result | FileCheck %s // Check that the attributes are shifted along with their corresponding arguments diff --git a/flang/test/Fir/abstract-results.fir b/flang/test/Fir/abstract-results.fir index 42ff2a5c8eb2..82f1cd33073f 100644 --- a/flang/test/Fir/abstract-results.fir +++ b/flang/test/Fir/abstract-results.fir @@ -1,10 +1,10 @@ // Test rewrite of functions that return fir.array<>, fir.type<>, fir.box<> to // functions that take an additional argument for the result. -// RUN: fir-opt %s --abstract-result-on-func-opt | FileCheck %s --check-prefix=FUNC-REF -// RUN: fir-opt %s --abstract-result-on-func-opt=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX -// RUN: fir-opt %s --abstract-result-on-global-opt | FileCheck %s --check-prefix=GLOBAL-REF -// RUN: fir-opt %s --abstract-result-on-global-opt=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX +// RUN: fir-opt %s --abstract-result | FileCheck %s --check-prefix=FUNC-REF +// RUN: fir-opt %s --abstract-result=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX +// RUN: fir-opt %s --abstract-result | FileCheck %s --check-prefix=GLOBAL-REF +// RUN: fir-opt %s --abstract-result=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX // ----------------------- Test declaration rewrite ---------------------------- diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index 80d3520bc7f7..28c597fc918c 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -74,11 +74,13 @@ func.func @_QQmain() { // PASSES-NEXT: (S) 0 num-dce'd - Number of operations DCE'd // PASSES-NEXT: BoxedProcedurePass -// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction'] // PASSES-NEXT: 'fir.global' Pipeline -// PASSES-NEXT: AbstractResultOnGlobalOpt +// PASSES-NEXT: AbstractResultOpt // PASSES-NEXT: 'func.func' Pipeline -// PASSES-NEXT: AbstractResultOnFuncOpt +// PASSES-NEXT: AbstractResultOpt +// PASSES-NEXT: 'omp.declare_reduction' Pipeline +// PASSES-NEXT: AbstractResultOpt // PASSES-NEXT: CodeGenRewrite // PASSES-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Fir/non-trivial-procedure-binding-description.f90 b/flang/test/Fir/non-trivial-procedure-binding-description.f90 index 695d7fdfe232..668928600157 100644 --- a/flang/test/Fir/non-trivial-procedure-binding-description.f90 +++ b/flang/test/Fir/non-trivial-procedure-binding-description.f90 @@ -1,5 +1,5 @@ ! RUN: %flang_fc1 -emit-mlir %s -o - | FileCheck %s --check-prefix=BEFORE -! RUN: %flang_fc1 -emit-mlir %s -o - | fir-opt --abstract-result-on-global-opt | FileCheck %s --check-prefix=AFTER +! RUN: %flang_fc1 -emit-mlir %s -o - | fir-opt --abstract-result | FileCheck %s --check-prefix=AFTER module a type f contains -- GitLab From c88b84d467a201129e329b0bca3425fef326db03 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 22 Apr 2024 09:32:27 +0100 Subject: [PATCH 134/357] [DAG] visitOR/visitORLike - merge repeated SDLoc calls. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 3cdb801bae7b..0c3eb3cabc88 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -457,7 +457,7 @@ namespace { SDValue visitAND(SDNode *N); SDValue visitANDLike(SDValue N0, SDValue N1, SDNode *N); SDValue visitOR(SDNode *N); - SDValue visitORLike(SDValue N0, SDValue N1, SDNode *N); + SDValue visitORLike(SDValue N0, SDValue N1, const SDLoc &DL); SDValue visitXOR(SDNode *N); SDValue SimplifyVCastOp(SDNode *N, const SDLoc &DL); SDValue SimplifyVBinOp(SDNode *N, const SDLoc &DL); @@ -7566,9 +7566,8 @@ SDValue DAGCombiner::MatchBSwapHWord(SDNode *N, SDValue N0, SDValue N1) { /// This contains all DAGCombine rules which reduce two values combined by /// an Or operation to a single value \see visitANDLike(). -SDValue DAGCombiner::visitORLike(SDValue N0, SDValue N1, SDNode *N) { +SDValue DAGCombiner::visitORLike(SDValue N0, SDValue N1, const SDLoc &DL) { EVT VT = N1.getValueType(); - SDLoc DL(N); // fold (or x, undef) -> -1 if (!LegalOperations && (N0.isUndef() || N1.isUndef())) @@ -7702,23 +7701,24 @@ SDValue DAGCombiner::visitOR(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); EVT VT = N1.getValueType(); + SDLoc DL(N); // x | x --> x if (N0 == N1) return N0; // fold (or c1, c2) -> c1|c2 - if (SDValue C = DAG.FoldConstantArithmetic(ISD::OR, SDLoc(N), VT, {N0, N1})) + if (SDValue C = DAG.FoldConstantArithmetic(ISD::OR, DL, VT, {N0, N1})) return C; // canonicalize constant to RHS if (DAG.isConstantIntBuildVectorOrConstantInt(N0) && !DAG.isConstantIntBuildVectorOrConstantInt(N1)) - return DAG.getNode(ISD::OR, SDLoc(N), VT, N1, N0); + return DAG.getNode(ISD::OR, DL, VT, N1, N0); // fold vector ops if (VT.isVector()) { - if (SDValue FoldedVOp = SimplifyVBinOp(N, SDLoc(N))) + if (SDValue FoldedVOp = SimplifyVBinOp(N, DL)) return FoldedVOp; // fold (or x, 0) -> x, vector edition @@ -7728,7 +7728,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) { // fold (or x, -1) -> -1, vector edition if (ISD::isConstantSplatVectorAllOnes(N1.getNode())) // do not return N1, because undef node may exist in N1 - return DAG.getAllOnesConstant(SDLoc(N), N1.getValueType()); + return DAG.getAllOnesConstant(DL, N1.getValueType()); // fold (or (shuf A, V_0, MA), (shuf B, V_0, MB)) -> (shuf A, B, Mask) // Do this only if the resulting type / shuffle is legal. @@ -7778,10 +7778,8 @@ SDValue DAGCombiner::visitOR(SDNode *N) { if (CanFold) { SDValue NewLHS = ZeroN00 ? N0.getOperand(1) : N0.getOperand(0); SDValue NewRHS = ZeroN10 ? N1.getOperand(1) : N1.getOperand(0); - SDValue LegalShuffle = - TLI.buildLegalVectorShuffle(VT, SDLoc(N), NewLHS, NewRHS, - Mask, DAG); + TLI.buildLegalVectorShuffle(VT, DL, NewLHS, NewRHS, Mask, DAG); if (LegalShuffle) return LegalShuffle; } @@ -7808,7 +7806,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) { if (SDValue R = foldAndOrOfSETCC(N, DAG)) return R; - if (SDValue Combined = visitORLike(N0, N1, N)) + if (SDValue Combined = visitORLike(N0, N1, DL)) return Combined; if (SDValue Combined = combineCarryDiamond(DAG, TLI, N0, N1, N)) @@ -7821,12 +7819,12 @@ SDValue DAGCombiner::visitOR(SDNode *N) { return BSwap; // reassociate or - if (SDValue ROR = reassociateOps(ISD::OR, SDLoc(N), N0, N1, N->getFlags())) + if (SDValue ROR = reassociateOps(ISD::OR, DL, N0, N1, N->getFlags())) return ROR; // Fold or(vecreduce(x), vecreduce(y)) -> vecreduce(or(x, y)) - if (SDValue SD = reassociateReduction(ISD::VECREDUCE_OR, ISD::OR, SDLoc(N), - VT, N0, N1)) + if (SDValue SD = + reassociateReduction(ISD::VECREDUCE_OR, ISD::OR, DL, VT, N0, N1)) return SD; // Canonicalize (or (and X, c1), c2) -> (and (or X, c2), c1|c2) @@ -7840,7 +7838,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) { {N1, N0.getOperand(1)})) { SDValue IOR = DAG.getNode(ISD::OR, SDLoc(N0), VT, N0.getOperand(0), N1); AddToWorklist(IOR.getNode()); - return DAG.getNode(ISD::AND, SDLoc(N), VT, COR, IOR); + return DAG.getNode(ISD::AND, DL, VT, COR, IOR); } } @@ -7855,7 +7853,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) { return V; // See if this is some rotate idiom. - if (SDValue Rot = MatchRotate(N0, N1, SDLoc(N))) + if (SDValue Rot = MatchRotate(N0, N1, DL)) return Rot; if (SDValue Load = MatchLoadCombine(N)) @@ -11534,7 +11532,7 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) { N2_2, Flags); } // Otherwise see if we can optimize to a better pattern. - if (SDValue Combined = visitORLike(N0, N2_0, N)) + if (SDValue Combined = visitORLike(N0, N2_0, DL)) return DAG.getNode(ISD::SELECT, DL, N1.getValueType(), Combined, N1, N2_2, Flags); } -- GitLab From bd84f5d5d71ee26d9552a9cd96ef058cfb8a39fc Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 22 Apr 2024 10:48:25 +0200 Subject: [PATCH 135/357] clang: Remove unnecessary pointer bitcast --- clang/lib/CodeGen/CGExprScalar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index c76052ff6280..40a5cd20c3d7 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1540,7 +1540,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, if (auto DstPT = dyn_cast(DstTy)) { // The source value may be an integer, or a pointer. if (isa(SrcTy)) - return Builder.CreateBitCast(Src, DstTy, "conv"); + return Src; assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); // First, convert to the correct width so that we control the kind of -- GitLab From ca9a44ef4791931fe77d123709fa1a9d18f827fd Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 22 Apr 2024 10:41:49 +0100 Subject: [PATCH 136/357] [DAG] visitORCommutative - use sd_match to reduce the need for commutative operand matching. NFCI. Use sd_match to match commutative inner AND/OR/XOR node arguments instead of some messy manual matching of each commutation. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0c3eb3cabc88..e6e0a1fc7d82 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7655,23 +7655,17 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1, } } - if (N0.getOpcode() == ISD::XOR) { - // fold or (xor x, y), x --> or x, y - // or (xor x, y), (x and/or y) --> or x, y - SDValue N00 = N0.getOperand(0); - SDValue N01 = N0.getOperand(1); - if (N00 == N1) - return DAG.getNode(ISD::OR, SDLoc(N), VT, N01, N1); - if (N01 == N1) - return DAG.getNode(ISD::OR, SDLoc(N), VT, N00, N1); + SDValue X, Y; - if (N1.getOpcode() == ISD::AND || N1.getOpcode() == ISD::OR) { - SDValue N10 = N1.getOperand(0); - SDValue N11 = N1.getOperand(1); - if ((N00 == N10 && N01 == N11) || (N00 == N11 && N01 == N10)) - return DAG.getNode(ISD::OR, SDLoc(N), VT, N00, N01); - } - } + // fold or (xor X, N1), N1 --> or X, N1 + if (sd_match(N0, m_Xor(m_Value(X), m_Specific(N1)))) + return DAG.getNode(ISD::OR, SDLoc(N), VT, X, N1); + + // fold or (xor x, y), (x and/or y) --> or x, y + if (sd_match(N0, m_Xor(m_Value(X), m_Value(Y))) && + (sd_match(N1, m_And(m_Specific(X), m_Specific(Y))) || + sd_match(N1, m_Or(m_Specific(X), m_Specific(Y))))) + return DAG.getNode(ISD::OR, SDLoc(N), VT, X, Y); if (SDValue R = foldLogicOfShifts(N, N0, N1, DAG)) return R; -- GitLab From 821935bb55449f708f822d0e381164ebbc33483c Mon Sep 17 00:00:00 2001 From: chuongg3 Date: Mon, 22 Apr 2024 10:47:09 +0100 Subject: [PATCH 137/357] [AArch64][GlobalISel] Combine Shuffles of G_CONCAT_VECTORS (#87489) Combines G_SHUFFLE_VECTOR whose sources comes from G_CONCAT_VECTORS into a single G_CONCAT_VECTORS instruction. a = G_CONCAT_VECTORS x, y, undef, undef b = G_CONCAT_VECTORS z, undef, undef, undef c = G_SHUFFLE_VECTORS a, b, <0, 1, 4, undef> ===> c = G_CONCAT_VECTORS x, y, z, undef` --- .../llvm/CodeGen/GlobalISel/CombinerHelper.h | 5 + .../include/llvm/Target/GlobalISel/Combine.td | 15 +- .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 77 +++++++ .../GlobalISel/combine-shufflevector.mir | 202 ++++++++++++++++++ 4 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-shufflevector.mir diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 3af32043391f..4b8aec8e8a5d 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -237,6 +237,11 @@ public: /// or an implicit_def if \p Ops is empty. void applyCombineConcatVectors(MachineInstr &MI, SmallVector &Ops); + bool matchCombineShuffleConcat(MachineInstr &MI, SmallVector &Ops); + /// Replace \p MI with a flattened build_vector with \p Ops + /// or an implicit_def if \p Ops is empty. + void applyCombineShuffleConcat(MachineInstr &MI, SmallVector &Ops); + /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS. /// Returns true if MI changed. /// diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 8568a7ae90e5..31b903e63d99 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -1513,6 +1513,18 @@ def combine_concat_vector : GICombineRule< [{ return Helper.matchCombineConcatVectors(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyCombineConcatVectors(*${root}, ${matchinfo}); }])>; +// Combines Shuffles of Concats +// a = G_CONCAT_VECTORS x, y, undef, undef +// b = G_CONCAT_VECTORS z, undef, undef, undef +// c = G_SHUFFLE_VECTORS a, b, <0, 1, 4, undef> +// ===> +// c = G_CONCAT_VECTORS x, y, z, undef +def combine_shuffle_concat : GICombineRule< + (defs root:$root, concat_matchinfo:$matchinfo), + (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, + [{ return Helper.matchCombineShuffleConcat(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyCombineShuffleConcat(*${root}, ${matchinfo}); }])>; + // match_extract_of_element must be the first! def vector_ops_combines: GICombineGroup<[ match_extract_of_element_undef_vector, @@ -1620,7 +1632,8 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines, and_or_disjoint_mask, fma_combines, fold_binop_into_select, sub_add_reg, select_to_minmax, redundant_binop_in_equality, fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors, - combine_concat_vector, double_icmp_zero_and_or_combine, match_addos]>; + combine_concat_vector, double_icmp_zero_and_or_combine, match_addos, + combine_shuffle_concat]>; // A combine group used to for prelegalizer combiners at -O0. The combines in // this group have been selected based on experiments to balance code size and diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 3829c33369b2..c5ee354f13b7 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -303,6 +303,83 @@ void CombinerHelper::applyCombineConcatVectors(MachineInstr &MI, replaceRegWith(MRI, DstReg, NewDstReg); } +bool CombinerHelper::matchCombineShuffleConcat(MachineInstr &MI, + SmallVector &Ops) { + ArrayRef Mask = MI.getOperand(3).getShuffleMask(); + auto ConcatMI1 = + dyn_cast(MRI.getVRegDef(MI.getOperand(1).getReg())); + auto ConcatMI2 = + dyn_cast(MRI.getVRegDef(MI.getOperand(2).getReg())); + if (!ConcatMI1 || !ConcatMI2) + return false; + + // Check that the sources of the Concat instructions have the same type + if (MRI.getType(ConcatMI1->getSourceReg(0)) != + MRI.getType(ConcatMI2->getSourceReg(0))) + return false; + + LLT ConcatSrcTy = MRI.getType(ConcatMI1->getReg(1)); + LLT ShuffleSrcTy1 = MRI.getType(MI.getOperand(1).getReg()); + unsigned ConcatSrcNumElt = ConcatSrcTy.getNumElements(); + for (unsigned i = 0; i < Mask.size(); i += ConcatSrcNumElt) { + // Check if the index takes a whole source register from G_CONCAT_VECTORS + // Assumes that all Sources of G_CONCAT_VECTORS are the same type + if (Mask[i] == -1) { + for (unsigned j = 1; j < ConcatSrcNumElt; j++) { + if (i + j >= Mask.size()) + return false; + if (Mask[i + j] != -1) + return false; + } + if (!isLegalOrBeforeLegalizer( + {TargetOpcode::G_IMPLICIT_DEF, {ConcatSrcTy}})) + return false; + Ops.push_back(0); + } else if (Mask[i] % ConcatSrcNumElt == 0) { + for (unsigned j = 1; j < ConcatSrcNumElt; j++) { + if (i + j >= Mask.size()) + return false; + if (Mask[i + j] != Mask[i] + static_cast(j)) + return false; + } + // Retrieve the source register from its respective G_CONCAT_VECTORS + // instruction + if (Mask[i] < ShuffleSrcTy1.getNumElements()) { + Ops.push_back(ConcatMI1->getSourceReg(Mask[i] / ConcatSrcNumElt)); + } else { + Ops.push_back(ConcatMI2->getSourceReg(Mask[i] / ConcatSrcNumElt - + ConcatMI1->getNumSources())); + } + } else { + return false; + } + } + + if (!isLegalOrBeforeLegalizer( + {TargetOpcode::G_CONCAT_VECTORS, + {MRI.getType(MI.getOperand(0).getReg()), ConcatSrcTy}})) + return false; + + return !Ops.empty(); +} + +void CombinerHelper::applyCombineShuffleConcat(MachineInstr &MI, + SmallVector &Ops) { + LLT SrcTy = MRI.getType(Ops[0]); + Register UndefReg = 0; + + for (unsigned i = 0; i < Ops.size(); i++) { + if (Ops[i] == 0) { + if (UndefReg == 0) + UndefReg = Builder.buildUndef(SrcTy).getReg(0); + Ops[i] = UndefReg; + } + } + + Builder.buildConcatVectors(MI.getOperand(0).getReg(), Ops); + MI.eraseFromParent(); +} + bool CombinerHelper::tryCombineShuffleVector(MachineInstr &MI) { SmallVector Ops; if (matchCombineShuffleVector(MI, Ops)) { diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-shufflevector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-shufflevector.mir new file mode 100644 index 000000000000..0de989f8be75 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-shufflevector.mir @@ -0,0 +1,202 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -o - -mtriple=aarch64-unknown-unknown -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s | FileCheck %s + +--- +name: shuffle_concat_1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1, $x2, $x3 + + ; CHECK-LABEL: name: shuffle_concat_1 + ; CHECK: liveins: $x0, $x1, $x2, $x3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %p2:_(p0) = COPY $x1 + ; CHECK-NEXT: %p3:_(p0) = COPY $x2 + ; CHECK-NEXT: %p4:_(p0) = COPY $x3 + ; CHECK-NEXT: %a:_(<4 x s8>) = G_LOAD %p4(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %b:_(<4 x s8>) = G_LOAD %p3(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %c:_(<4 x s8>) = G_LOAD %p2(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: %z:_(<16 x s8>) = G_CONCAT_VECTORS %a(<4 x s8>), %b(<4 x s8>), %c(<4 x s8>), [[DEF]](<4 x s8>) + ; CHECK-NEXT: $q0 = COPY %z(<16 x s8>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 + %p1:_(p0) = COPY $x0 + %p2:_(p0) = COPY $x1 + %p3:_(p0) = COPY $x2 + %p4:_(p0) = COPY $x3 + + %ImpDef:_(<4 x s8>) = G_IMPLICIT_DEF + %a:_(<4 x s8>) = G_LOAD %p4:_(p0) :: (load (<4 x s8>)) + %b:_(<4 x s8>) = G_LOAD %p3:_(p0) :: (load (<4 x s8>)) + %c:_(<4 x s8>) = G_LOAD %p2:_(p0) :: (load (<4 x s8>)) + %d:_(<4 x s8>) = G_LOAD %p1:_(p0) :: (load (<4 x s8>)) + + %x:_(<16 x s8>) = G_SHUFFLE_VECTOR %a:_(<4 x s8>), %b:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, undef, undef, undef, undef, undef, undef, undef, undef) + %y:_(<16 x s8>) = G_SHUFFLE_VECTOR %c:_(<4 x s8>), %d:_, shufflemask(0, 1, 2, 3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef) + %z:_(<16 x s8>) = G_SHUFFLE_VECTOR %x:_(<16 x s8>), %y:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, -1, -1, -1, -1) + + $q0 = COPY %z(<16 x s8>) + RET_ReallyLR implicit $q0 +... + +--- +name: shuffle_concat_2 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1, $x2, $x3 + + ; CHECK-LABEL: name: shuffle_concat_2 + ; CHECK: liveins: $x0, $x1, $x2, $x3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %p1:_(p0) = COPY $x0 + ; CHECK-NEXT: %p2:_(p0) = COPY $x1 + ; CHECK-NEXT: %p3:_(p0) = COPY $x2 + ; CHECK-NEXT: %p4:_(p0) = COPY $x3 + ; CHECK-NEXT: %a:_(<4 x s8>) = G_LOAD %p4(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %b:_(<4 x s8>) = G_LOAD %p3(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %c:_(<4 x s8>) = G_LOAD %p2(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %d:_(<4 x s8>) = G_LOAD %p1(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %z:_(<16 x s8>) = G_CONCAT_VECTORS %a(<4 x s8>), %b(<4 x s8>), %c(<4 x s8>), %d(<4 x s8>) + ; CHECK-NEXT: $q0 = COPY %z(<16 x s8>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 + %p1:_(p0) = COPY $x0 + %p2:_(p0) = COPY $x1 + %p3:_(p0) = COPY $x2 + %p4:_(p0) = COPY $x3 + + %ImpDef:_(<4 x s8>) = G_IMPLICIT_DEF + %a:_(<4 x s8>) = G_LOAD %p4:_(p0) :: (load (<4 x s8>)) + %b:_(<4 x s8>) = G_LOAD %p3:_(p0) :: (load (<4 x s8>)) + %c:_(<4 x s8>) = G_LOAD %p2:_(p0) :: (load (<4 x s8>)) + %d:_(<4 x s8>) = G_LOAD %p1:_(p0) :: (load (<4 x s8>)) + + %v:_(<16 x s8>) = G_SHUFFLE_VECTOR %a:_(<4 x s8>), %b:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, undef, undef, undef, undef, undef, undef, undef, undef) + %w:_(<16 x s8>) = G_SHUFFLE_VECTOR %c:_(<4 x s8>), %ImpDef:_, shufflemask(0, 1, 2, 3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef) + %x:_(<16 x s8>) = G_SHUFFLE_VECTOR %v:_(<16 x s8>), %w:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, undef, undef, undef, undef) + %y:_(<16 x s8>) = G_SHUFFLE_VECTOR %d:_(<4 x s8>), %ImpDef:_, shufflemask(0, 1, 2, 3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef) + %z:_(<16 x s8>) = G_SHUFFLE_VECTOR %x:_(<16 x s8>), %y:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19) + + $q0 = COPY %z(<16 x s8>) + RET_ReallyLR implicit $q0 +... + +--- +name: shuffle_concat_3 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1, $x2, $x3 + + ; CHECK-LABEL: name: shuffle_concat_3 + ; CHECK: liveins: $x0, $x1, $x2, $x3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %p2:_(p0) = COPY $x1 + ; CHECK-NEXT: %p3:_(p0) = COPY $x2 + ; CHECK-NEXT: %p4:_(p0) = COPY $x3 + ; CHECK-NEXT: %a:_(<4 x s8>) = G_LOAD %p4(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %b:_(<4 x s8>) = G_LOAD %p3(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %c:_(<4 x s8>) = G_LOAD %p2(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<16 x s8>) = G_CONCAT_VECTORS %a(<4 x s8>), %b(<4 x s8>), [[DEF]](<4 x s8>), [[DEF]](<4 x s8>) + ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<16 x s8>) = G_CONCAT_VECTORS %c(<4 x s8>), [[DEF]](<4 x s8>), [[DEF]](<4 x s8>), [[DEF]](<4 x s8>) + ; CHECK-NEXT: %z:_(<16 x s8>) = G_SHUFFLE_VECTOR [[CONCAT_VECTORS]](<16 x s8>), [[CONCAT_VECTORS1]], shufflemask(0, undef, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, undef, undef, undef, undef) + ; CHECK-NEXT: $q0 = COPY %z(<16 x s8>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 + %p1:_(p0) = COPY $x0 + %p2:_(p0) = COPY $x1 + %p3:_(p0) = COPY $x2 + %p4:_(p0) = COPY $x3 + + %ImpDef:_(<4 x s8>) = G_IMPLICIT_DEF + %a:_(<4 x s8>) = G_LOAD %p4:_(p0) :: (load (<4 x s8>)) + %b:_(<4 x s8>) = G_LOAD %p3:_(p0) :: (load (<4 x s8>)) + %c:_(<4 x s8>) = G_LOAD %p2:_(p0) :: (load (<4 x s8>)) + %d:_(<4 x s8>) = G_LOAD %p1:_(p0) :: (load (<4 x s8>)) + + %x:_(<16 x s8>) = G_SHUFFLE_VECTOR %a:_(<4 x s8>), %b:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, undef, undef, undef, undef, undef, undef, undef, undef) + %y:_(<16 x s8>) = G_SHUFFLE_VECTOR %c:_(<4 x s8>), %d:_, shufflemask(0, 1, 2, 3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef) + %z:_(<16 x s8>) = G_SHUFFLE_VECTOR %x:_(<16 x s8>), %y:_, shufflemask(0, -1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, -1, -1, -1, -1) + + $q0 = COPY %z(<16 x s8>) + RET_ReallyLR implicit $q0 +... + +--- +name: shuffle_concat_4 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1, $x2, $x3 + + ; CHECK-LABEL: name: shuffle_concat_4 + ; CHECK: liveins: $x0, $x1, $x2, $x3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %p2:_(p0) = COPY $x1 + ; CHECK-NEXT: %p4:_(p0) = COPY $x3 + ; CHECK-NEXT: %a:_(<4 x s8>) = G_LOAD %p4(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %c:_(<4 x s8>) = G_LOAD %p2(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: %z:_(<16 x s8>) = G_CONCAT_VECTORS %a(<4 x s8>), [[DEF]](<4 x s8>), %c(<4 x s8>), [[DEF]](<4 x s8>) + ; CHECK-NEXT: $q0 = COPY %z(<16 x s8>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 + %p1:_(p0) = COPY $x0 + %p2:_(p0) = COPY $x1 + %p3:_(p0) = COPY $x2 + %p4:_(p0) = COPY $x3 + + %ImpDef:_(<4 x s8>) = G_IMPLICIT_DEF + %a:_(<4 x s8>) = G_LOAD %p4:_(p0) :: (load (<4 x s8>)) + %b:_(<4 x s8>) = G_LOAD %p3:_(p0) :: (load (<4 x s8>)) + %c:_(<4 x s8>) = G_LOAD %p2:_(p0) :: (load (<4 x s8>)) + %d:_(<4 x s8>) = G_LOAD %p1:_(p0) :: (load (<4 x s8>)) + + %x:_(<16 x s8>) = G_SHUFFLE_VECTOR %a:_(<4 x s8>), %b:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, undef, undef, undef, undef, undef, undef, undef, undef) + %y:_(<16 x s8>) = G_SHUFFLE_VECTOR %c:_(<4 x s8>), %d:_, shufflemask(0, 1, 2, 3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef) + %z:_(<16 x s8>) = G_SHUFFLE_VECTOR %x:_(<16 x s8>), %y:_, shufflemask(0, 1, 2, 3, -1, -1, -1, -1, 16, 17, 18, 19, -1, -1, -1, -1) + + $q0 = COPY %z(<16 x s8>) + RET_ReallyLR implicit $q0 +... + +--- +name: shuffle_concat_5 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x1, $x2, $x3 + + ; CHECK-LABEL: name: shuffle_concat_5 + ; CHECK: liveins: $x0, $x1, $x2, $x3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %p2:_(p0) = COPY $x1 + ; CHECK-NEXT: %p3:_(p0) = COPY $x2 + ; CHECK-NEXT: %p4:_(p0) = COPY $x3 + ; CHECK-NEXT: %a:_(<4 x s8>) = G_LOAD %p4(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %b:_(<4 x s8>) = G_LOAD %p3(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: %c:_(<4 x s8>) = G_LOAD %p2(p0) :: (load (<4 x s8>)) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<16 x s8>) = G_CONCAT_VECTORS %a(<4 x s8>), %b(<4 x s8>), [[DEF]](<4 x s8>), [[DEF]](<4 x s8>) + ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<16 x s8>) = G_CONCAT_VECTORS %c(<4 x s8>), [[DEF]](<4 x s8>), [[DEF]](<4 x s8>), [[DEF]](<4 x s8>) + ; CHECK-NEXT: %z:_(<16 x s8>) = G_SHUFFLE_VECTOR [[CONCAT_VECTORS]](<16 x s8>), [[CONCAT_VECTORS1]], shufflemask(undef, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, undef, undef, undef, undef) + ; CHECK-NEXT: $q0 = COPY %z(<16 x s8>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 + %p1:_(p0) = COPY $x0 + %p2:_(p0) = COPY $x1 + %p3:_(p0) = COPY $x2 + %p4:_(p0) = COPY $x3 + + %ImpDef:_(<4 x s8>) = G_IMPLICIT_DEF + %a:_(<4 x s8>) = G_LOAD %p4:_(p0) :: (load (<4 x s8>)) + %b:_(<4 x s8>) = G_LOAD %p3:_(p0) :: (load (<4 x s8>)) + %c:_(<4 x s8>) = G_LOAD %p2:_(p0) :: (load (<4 x s8>)) + %d:_(<4 x s8>) = G_LOAD %p1:_(p0) :: (load (<4 x s8>)) + + %x:_(<16 x s8>) = G_SHUFFLE_VECTOR %a:_(<4 x s8>), %b:_, shufflemask(0, 1, 2, 3, 4, 5, 6, 7, undef, undef, undef, undef, undef, undef, undef, undef) + %y:_(<16 x s8>) = G_SHUFFLE_VECTOR %c:_(<4 x s8>), %d:_, shufflemask(0, 1, 2, 3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef) + %z:_(<16 x s8>) = G_SHUFFLE_VECTOR %x:_(<16 x s8>), %y:_, shufflemask(-1, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, -1, -1, -1, -1) + + $q0 = COPY %z(<16 x s8>) + RET_ReallyLR implicit $q0 +... -- GitLab From c8e5ad4e123a5fb082355947a896980464689c31 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 22 Apr 2024 10:50:36 +0100 Subject: [PATCH 138/357] Revert "[TBAA] Add verifier for tbaa.struct metadata (#86709)" This reverts commit 7dbba39e583a3fd64e7e6b947251c035e483f054. Revert as there are reports this triggers during ThinLTO in some configurations. --- 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 0d6db3da9e61..edad3be9a3e0 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5123,9 +5123,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)) @@ -7462,35 +7459,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 f57ec8d58982..28d5933ab9b8 100644 --- a/llvm/test/Transforms/Scalarizer/basic.ll +++ b/llvm/test/Transforms/Scalarizer/basic.ll @@ -884,6 +884,5 @@ define <2 x i8> @test_copy_trunc_flags(<2 x i32> %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 fdc8c5440041ac53726d0b3587762ceeb8cbbb4f Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 22 Apr 2024 11:56:19 +0200 Subject: [PATCH 139/357] [flang][driver] Avoid mentions of Clang in Flang's command line reference. (#88932) The help text was not updated in #87360. Clang is also mentioned for the diagnostic warnings reference, which mostly applies to C/C++/Obj-C, not Fortran. #81726 already tried to fix this, and I don't know a better solution. --- clang/include/clang/Driver/Options.td | 8 ++++++-- flang/test/Driver/driver-help-hidden.f90 | 2 +- flang/test/Driver/driver-help.f90 | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 52d161703f96..9f86808145d9 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -807,8 +807,12 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">, "Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>, Visibility<[ClangOption, FlangOption]>, - HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " - "Clang will use the GCC installation with the largest version">; + HelpText< + "Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " + "Clang will use the GCC installation with the largest version">, + HelpTextForVariants<[FlangOption], + "Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " + "Flang will use the GCC installation with the largest version">; def gcc_triple_EQ : Joined<["--"], "gcc-triple=">, HelpText<"Search for the GCC installation with the specified triple.">; def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>, diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 index de2fe3048f99..b5bb0f1c1b25 100644 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -109,7 +109,7 @@ ! CHECK-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! CHECK-NEXT: --gcc-install-dir= ! CHECK-NEXT: Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation -! CHECK-NEXT: --gcc-toolchain= Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Clang will use the GCC installation with the largest version +! CHECK-NEXT: --gcc-toolchain= Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Flang will use the GCC installation with the largest version ! CHECK-NEXT: -gline-directives-only Emit debug line info directives only ! CHECK-NEXT: -gline-tables-only Emit debug line number tables only ! CHECK-NEXT: -gpulibc Link the LLVM C Library for GPUs diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index b258eb59c186..0b0a493baf07 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -97,7 +97,7 @@ ! HELP-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! HELP-NEXT: --gcc-install-dir= ! HELP-NEXT: Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation -! HELP-NEXT: --gcc-toolchain= Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Clang will use the GCC installation with the largest version +! HELP-NEXT: --gcc-toolchain= Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Flang will use the GCC installation with the largest version ! HELP-NEXT: -gline-directives-only Emit debug line info directives only ! HELP-NEXT: -gline-tables-only Emit debug line number tables only ! HELP-NEXT: -gpulibc Link the LLVM C Library for GPUs -- GitLab From 087b33bbff1ab966656a81f9dd8e136fbd966f58 Mon Sep 17 00:00:00 2001 From: abidh Date: Mon, 22 Apr 2024 11:19:05 +0100 Subject: [PATCH 140/357] [flang] Default -g to full debug info. (#89418) Currently, -g defaults to line tables only. This PR changes that to full debug information. This will allow us to test/use the upcoming debug info changes. --- clang/lib/Driver/ToolChains/Flang.cpp | 2 +- flang/lib/Frontend/CompilerInvocation.cpp | 1 + flang/test/Driver/debug-level.f90 | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 flang/test/Driver/debug-level.f90 diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index b46bac24503c..abe0b9316760 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -118,7 +118,7 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const { Arg *gNArg = Args.getLastArg(options::OPT_gN_Group); DebugInfoKind = debugLevelToInfoKind(*gNArg); } else if (Args.hasArg(options::OPT_g_Flag)) { - DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly; + DebugInfoKind = llvm::codegenoptions::FullDebugInfo; } else { DebugInfoKind = llvm::codegenoptions::NoDebugInfo; } diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index e432c5a30275..f1b7b5397539 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -145,6 +145,7 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts, } opts.setDebugInfo(val.value()); if (val != llvm::codegenoptions::DebugLineTablesOnly && + val != llvm::codegenoptions::FullDebugInfo && val != llvm::codegenoptions::NoDebugInfo) { const auto debugWarning = diags.getCustomDiagID( clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0"); diff --git a/flang/test/Driver/debug-level.f90 b/flang/test/Driver/debug-level.f90 new file mode 100644 index 000000000000..bc0aee166e6a --- /dev/null +++ b/flang/test/Driver/debug-level.f90 @@ -0,0 +1,7 @@ +! RUN: %flang %s -g -c -### 2>&1 | FileCheck %s --check-prefix=FULL +! RUN: %flang %s -g1 -c -### 2>&1 | FileCheck %s --check-prefix=LINE +! RUN: %flang %s -gline-tables-only -c -### 2>&1 | FileCheck %s --check-prefix=LINE + +! LINE: -debug-info-kind=line-tables-only +! FULL: -debug-info-kind=standalone + -- GitLab From 5b6db43f29ac5a114ce6c61010ddd6553c0770c0 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 22 Apr 2024 12:22:54 +0200 Subject: [PATCH 141/357] AMDGPU: Simplify DS atomicrmw fadd handling (#89468) DS atomic fadd F32 does respect the denormal mode, so we do not need to consider the expected FP mode or unsafe-fp-atomics attribute. They don't respect the rounding mode, but we don't care outside of strictfp. This also reveals the fp-mode-is-flush check has been missing in the cases that should be considering it alongside amdgpu-unsafe-fp-atomics. This also stops considering the case where flushing is enabled for f64, as flushing isn't mandated and we barely handle this case. --- llvm/lib/Target/AMDGPU/AMDGPU.td | 2 +- .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 2 +- llvm/lib/Target/AMDGPU/DSInstructions.td | 8 +- llvm/lib/Target/AMDGPU/GCNSubtarget.h | 3 +- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 47 ++- .../AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll | 38 +- .../AMDGPU/atomics-hw-remarks-gfx90a.ll | 1 - .../CodeGen/AMDGPU/fp64-atomics-gfx90a.ll | 52 +-- .../AMDGPU/expand-atomic-rmw-fadd.ll | 344 +++++++++++++++--- 9 files changed, 342 insertions(+), 155 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td index 9b0955015999..5c2c6d4b13c6 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -1896,7 +1896,7 @@ def HasVINTERPEncoding : Predicate<"Subtarget->hasVINTERPEncoding()">, def HasDSAddTid : Predicate<"Subtarget->getGeneration() >= AMDGPUSubtarget::GFX9">, AssemblerPredicate<(all_of FeatureGFX9Insts)>; -def HasLDSFPAtomicAdd : Predicate<"Subtarget->hasLDSFPAtomicAdd()">, +def HasLDSFPAtomicAddF32 : Predicate<"Subtarget->hasLDSFPAtomicAddF32()">, AssemblerPredicate<(all_of FeatureGFX8Insts)>; def HasAddNoCarryInsts : Predicate<"Subtarget->hasAddNoCarry()">, diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index e55d1de01b4f..780dfaae11ef 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -1624,7 +1624,7 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_, } auto &Atomic = getActionDefinitionsBuilder(G_ATOMICRMW_FADD); - if (ST.hasLDSFPAtomicAdd()) { + if (ST.hasLDSFPAtomicAddF32()) { Atomic.legalFor({{S32, LocalPtr}, {S32, RegionPtr}}); if (ST.hasLdsAtomicAddF64()) Atomic.legalFor({{S64, LocalPtr}}); diff --git a/llvm/lib/Target/AMDGPU/DSInstructions.td b/llvm/lib/Target/AMDGPU/DSInstructions.td index 0773ef7f3234..d63f04ab6d4c 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -443,7 +443,7 @@ defm DS_AND_B32 : DS_1A1D_NORET_mc<"ds_and_b32">; defm DS_OR_B32 : DS_1A1D_NORET_mc<"ds_or_b32">; defm DS_XOR_B32 : DS_1A1D_NORET_mc<"ds_xor_b32">; -let SubtargetPredicate = HasLDSFPAtomicAdd in { +let SubtargetPredicate = HasLDSFPAtomicAddF32 in { defm DS_ADD_F32 : DS_1A1D_NORET_mc<"ds_add_f32">; } @@ -523,7 +523,7 @@ defm DS_MAX_F64 : DS_1A1D_NORET_mc<"ds_max_f64", VReg_64>; defm DS_ADD_RTN_U32 : DS_1A1D_RET_mc<"ds_add_rtn_u32", VGPR_32>; -let SubtargetPredicate = HasLDSFPAtomicAdd in { +let SubtargetPredicate = HasLDSFPAtomicAddF32 in { defm DS_ADD_RTN_F32 : DS_1A1D_RET_mc<"ds_add_rtn_f32", VGPR_32>; } defm DS_SUB_RTN_U32 : DS_1A1D_RET_mc<"ds_sub_rtn_u32", VGPR_32>; @@ -697,7 +697,7 @@ def DS_BPERMUTE_B32 : DS_1A1D_PERMUTE <"ds_bpermute_b32", } // let SubtargetPredicate = isGFX8Plus -let SubtargetPredicate = HasLDSFPAtomicAdd, OtherPredicates = [HasDsSrc2Insts] in { +let SubtargetPredicate = HasLDSFPAtomicAddF32, OtherPredicates = [HasDsSrc2Insts] in { def DS_ADD_SRC2_F32 : DS_1A<"ds_add_src2_f32">; } @@ -1088,7 +1088,7 @@ let SubtargetPredicate = isGFX11Plus in { defm : DSAtomicCmpXChg_mc; } -let SubtargetPredicate = HasLDSFPAtomicAdd in { +let SubtargetPredicate = HasLDSFPAtomicAddF32 in { defm : DSAtomicRetNoRetPat_mc; } diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.h b/llvm/lib/Target/AMDGPU/GCNSubtarget.h index 8a4a46ce50d1..2ca5ae306b11 100644 --- a/llvm/lib/Target/AMDGPU/GCNSubtarget.h +++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.h @@ -960,7 +960,8 @@ public: return HasScalarAtomics; } - bool hasLDSFPAtomicAdd() const { return GFX8Insts; } + bool hasLDSFPAtomicAddF32() const { return GFX8Insts; } + bool hasLDSFPAtomicAddF64() const { return GFX90AInsts; } /// \returns true if the subtarget has the v_permlanex16_b32 instruction. bool hasPermLaneX16() const { return getGeneration() >= GFX10; } diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index c4592d43f4f8..12b7f05c4463 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -15977,6 +15977,8 @@ bool SITargetLowering::isKnownNeverNaNForTargetNode(SDValue Op, SNaN, Depth); } +#if 0 +// FIXME: This should be checked before unsafe fp atomics are enabled // Global FP atomic instructions have a hardcoded FP mode and do not support // FP32 denormals, and only support v2f16 denormals. static bool fpModeMatchesGlobalFPAtomicMode(const AtomicRMWInst *RMW) { @@ -15986,6 +15988,7 @@ static bool fpModeMatchesGlobalFPAtomicMode(const AtomicRMWInst *RMW) { return DenormMode == DenormalMode::getPreserveSign(); return DenormMode == DenormalMode::getIEEE(); } +#endif // The amdgpu-unsafe-fp-atomics attribute enables generation of unsafe // floating point atomic instructions. May generate more efficient code, @@ -16046,8 +16049,31 @@ SITargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { case AtomicRMWInst::FAdd: { Type *Ty = RMW->getType(); - if (Ty->isHalfTy()) + // TODO: Handle REGION_ADDRESS + if (AS == AMDGPUAS::LOCAL_ADDRESS) { + // DS F32 FP atomics do respect the denormal mode, but the rounding mode + // is fixed to round-to-nearest-even. + // + // F64 / PK_F16 / PK_BF16 never flush and are also fixed to + // round-to-nearest-even. + // + // We ignore the rounding mode problem, even in strictfp. The C++ standard + // suggests it is OK if the floating-point mode may not match the calling + // thread. + if (Ty->isFloatTy()) { + return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None + : AtomicExpansionKind::CmpXChg; + } + + if (Ty->isDoubleTy()) { + // Ignores denormal mode, but we don't consider flushing mandatory. + return Subtarget->hasLDSFPAtomicAddF64() ? AtomicExpansionKind::None + : AtomicExpansionKind::CmpXChg; + } + + // TODO: Handle v2f16/v2bf16 cases for gfx940 return AtomicExpansionKind::CmpXChg; + } if (!Ty->isFloatTy() && (!Subtarget->hasGFX90AInsts() || !Ty->isDoubleTy())) return AtomicExpansionKind::CmpXChg; @@ -16091,7 +16117,7 @@ SITargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { // space. If it is in global address space, we emit the global atomic // fadd; if it is in shared address space, we emit the LDS atomic fadd. if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy() && - Subtarget->hasLDSFPAtomicAdd()) { + Subtarget->hasLDSFPAtomicAddF32()) { if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts()) return AtomicExpansionKind::Expand; if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts()) @@ -16101,23 +16127,6 @@ SITargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { return AtomicExpansionKind::CmpXChg; } - // DS FP atomics do respect the denormal mode, but the rounding mode is - // fixed to round-to-nearest-even. - // The only exception is DS_ADD_F64 which never flushes regardless of mode. - if (AS == AMDGPUAS::LOCAL_ADDRESS && Subtarget->hasLDSFPAtomicAdd()) { - if (!Ty->isDoubleTy()) - return AtomicExpansionKind::None; - - if (fpModeMatchesGlobalFPAtomicMode(RMW)) - return AtomicExpansionKind::None; - - return RMW->getFunction() - ->getFnAttribute("amdgpu-unsafe-fp-atomics") - .getValueAsString() == "true" - ? ReportUnsafeHWInst(AtomicExpansionKind::None) - : AtomicExpansionKind::CmpXChg; - } - return AtomicExpansionKind::CmpXChg; } case AtomicRMWInst::FMin: diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll index 1a76f8cf87ff..4e94a646f6da 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll @@ -2074,28 +2074,17 @@ define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush_safe(ptr addrsp ; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 ; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 ; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc -; GFX90A-NEXT: s_cbranch_execz .LBB67_3 +; GFX90A-NEXT: s_cbranch_execz .LBB67_2 ; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 ; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] ; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 ; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_mov_b32_e32 v4, s0 -; GFX90A-NEXT: ds_read_b64 v[2:3], v4 -; GFX90A-NEXT: s_mov_b64 s[0:1], 0 -; GFX90A-NEXT: .LBB67_2: ; %atomicrmw.start -; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] -; GFX90A-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] +; GFX90A-NEXT: v_mov_b32_e32 v2, s0 +; GFX90A-NEXT: ds_add_f64 v2, v[0:1] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] -; GFX90A-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[6:7], v[6:7] op_sel:[0,1] -; GFX90A-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX90A-NEXT: s_cbranch_execnz .LBB67_2 -; GFX90A-NEXT: .LBB67_3: +; GFX90A-NEXT: .LBB67_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat_flush_safe: @@ -2106,28 +2095,17 @@ define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush_safe(ptr addrsp ; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 ; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 ; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc -; GFX940-NEXT: s_cbranch_execz .LBB67_3 +; GFX940-NEXT: s_cbranch_execz .LBB67_2 ; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 ; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] ; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 ; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_mov_b32_e32 v4, s0 -; GFX940-NEXT: ds_read_b64 v[2:3], v4 -; GFX940-NEXT: s_mov_b64 s[0:1], 0 -; GFX940-NEXT: .LBB67_2: ; %atomicrmw.start -; GFX940-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] -; GFX940-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] +; GFX940-NEXT: v_mov_b32_e32 v2, s0 +; GFX940-NEXT: ds_add_f64 v2, v[0:1] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] -; GFX940-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX940-NEXT: v_mov_b64_e32 v[2:3], v[6:7] -; GFX940-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX940-NEXT: s_cbranch_execnz .LBB67_2 -; GFX940-NEXT: .LBB67_3: +; GFX940-NEXT: .LBB67_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst diff --git a/llvm/test/CodeGen/AMDGPU/atomics-hw-remarks-gfx90a.ll b/llvm/test/CodeGen/AMDGPU/atomics-hw-remarks-gfx90a.ll index 001a4e999aee..b3fb67a7d7e0 100644 --- a/llvm/test/CodeGen/AMDGPU/atomics-hw-remarks-gfx90a.ll +++ b/llvm/test/CodeGen/AMDGPU/atomics-hw-remarks-gfx90a.ll @@ -1,7 +1,6 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx90a -verify-machineinstrs --pass-remarks=si-lower \ ; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=GFX90A-HW -; GFX90A-HW: Hardware instruction generated for atomic fadd operation at memory scope system due to an unsafe request. ; GFX90A-HW: Hardware instruction generated for atomic fadd operation at memory scope agent due to an unsafe request. ; GFX90A-HW: Hardware instruction generated for atomic fadd operation at memory scope workgroup due to an unsafe request. ; GFX90A-HW: Hardware instruction generated for atomic fadd operation at memory scope wavefront due to an unsafe request. diff --git a/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll b/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll index a948fab8f1c1..121fab51024f 100644 --- a/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll +++ b/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll @@ -2213,29 +2213,17 @@ define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush_safe(ptr addrsp ; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 ; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 ; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc -; GFX90A-NEXT: s_cbranch_execz .LBB72_3 +; GFX90A-NEXT: s_cbranch_execz .LBB72_2 ; GFX90A-NEXT: ; %bb.1: -; GFX90A-NEXT: s_load_dword s4, s[0:1], 0x24 -; GFX90A-NEXT: s_bcnt1_i32_b64 s0, s[2:3] -; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_mov_b32_e32 v0, s4 -; GFX90A-NEXT: ds_read_b64 v[2:3], v0 -; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 ; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 -; GFX90A-NEXT: s_mov_b64 s[0:1], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, s4 -; GFX90A-NEXT: .LBB72_2: ; %atomicrmw.start -; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] -; GFX90A-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] +; GFX90A-NEXT: v_mov_b32_e32 v2, s0 +; GFX90A-NEXT: ds_add_f64 v2, v[0:1] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] -; GFX90A-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[6:7], v[6:7] op_sel:[0,1] -; GFX90A-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX90A-NEXT: s_cbranch_execnz .LBB72_2 -; GFX90A-NEXT: .LBB72_3: +; GFX90A-NEXT: .LBB72_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat_flush_safe: @@ -2245,29 +2233,17 @@ define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush_safe(ptr addrsp ; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 ; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 ; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc -; GFX940-NEXT: s_cbranch_execz .LBB72_3 +; GFX940-NEXT: s_cbranch_execz .LBB72_2 ; GFX940-NEXT: ; %bb.1: -; GFX940-NEXT: s_load_dword s4, s[0:1], 0x24 -; GFX940-NEXT: s_bcnt1_i32_b64 s0, s[2:3] -; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-NEXT: ds_read_b64 v[2:3], v0 -; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 ; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 -; GFX940-NEXT: s_mov_b64 s[0:1], 0 -; GFX940-NEXT: v_mov_b32_e32 v4, s4 -; GFX940-NEXT: .LBB72_2: ; %atomicrmw.start -; GFX940-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] -; GFX940-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] +; GFX940-NEXT: v_mov_b32_e32 v2, s0 +; GFX940-NEXT: ds_add_f64 v2, v[0:1] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] -; GFX940-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX940-NEXT: v_mov_b64_e32 v[2:3], v[6:7] -; GFX940-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX940-NEXT: s_cbranch_execnz .LBB72_2 -; GFX940-NEXT: .LBB72_3: +; GFX940-NEXT: .LBB72_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll index 337e51f9a912..17318b2c62ca 100644 --- a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll @@ -3670,84 +3670,308 @@ define double @test_atomicrmw_fadd_f64_dyndenorm_global_system_ret__amdgpu_ignor } define void @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret(ptr addrspace(3) %ptr, double %value) #5 { -; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( -; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 -; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] -; ALL: atomicrmw.start: -; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] -; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 -; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 -; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 -; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 -; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 -; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double -; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] -; ALL: atomicrmw.end: -; ALL-NEXT: ret void +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; GFX90A-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8 +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8 +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void ; %unused = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic ret void } define double @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret(ptr addrspace(3) %ptr, double %value) #5 { -; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( -; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 -; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] -; ALL: atomicrmw.start: -; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] -; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 -; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 -; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 -; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 -; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 -; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double -; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] -; ALL: atomicrmw.end: -; ALL-NEXT: ret double [[TMP5]] +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret double [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; GFX90A-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8 +; GFX90A-NEXT: ret double [[RET]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8 +; GFX940-NEXT: ret double [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] ; %ret = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic ret double %ret } define void @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr, double %value) #5 { -; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( -; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 -; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] -; ALL: atomicrmw.start: -; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] -; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 -; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 -; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 -; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 -; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 -; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double -; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] -; ALL: atomicrmw.end: -; ALL-NEXT: ret void +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret void +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret void +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret void +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX90A-NEXT: ret void +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[UNUSED:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret void +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_noret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret void ; %unused = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 ret void } define double @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode(ptr addrspace(3) %ptr, double %value) #5 { -; ALL-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( -; ALL-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 -; ALL-NEXT: br label [[ATOMICRMW_START:%.*]] -; ALL: atomicrmw.start: -; ALL-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] -; ALL-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] -; ALL-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 -; ALL-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 -; ALL-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 -; ALL-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 -; ALL-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 -; ALL-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double -; ALL-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] -; ALL: atomicrmw.end: -; ALL-NEXT: ret double [[TMP5]] +; CI-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; CI-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; CI-NEXT: br label [[ATOMICRMW_START:%.*]] +; CI: atomicrmw.start: +; CI-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; CI-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; CI-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; CI-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; CI-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; CI-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; CI-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; CI-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; CI-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; CI: atomicrmw.end: +; CI-NEXT: ret double [[TMP5]] +; +; GFX9-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; GFX9-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX9-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX9: atomicrmw.start: +; GFX9-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX9-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX9-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX9-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX9-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX9-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX9-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX9-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX9-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX9: atomicrmw.end: +; GFX9-NEXT: ret double [[TMP5]] +; +; GFX908-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; GFX908-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX908-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX908: atomicrmw.start: +; GFX908-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX908-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX908-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX908-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX908-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX908-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX908-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX908-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX908-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX908: atomicrmw.end: +; GFX908-NEXT: ret double [[TMP5]] +; +; GFX90A-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; GFX90A-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX90A-NEXT: ret double [[RET]] +; +; GFX940-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; GFX940-NEXT: [[RET:%.*]] = atomicrmw fadd ptr addrspace(3) [[PTR:%.*]], double [[VALUE:%.*]] monotonic, align 8, !amdgpu.ignore.denormal.mode [[META0]] +; GFX940-NEXT: ret double [[RET]] +; +; GFX11-LABEL: @test_atomicrmw_fadd_f64_dyndenorm_local_system_ret__amdgpu_ignore_denormal_mode( +; GFX11-NEXT: [[TMP1:%.*]] = load double, ptr addrspace(3) [[PTR:%.*]], align 8 +; GFX11-NEXT: br label [[ATOMICRMW_START:%.*]] +; GFX11: atomicrmw.start: +; GFX11-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ] +; GFX11-NEXT: [[NEW:%.*]] = fadd double [[LOADED]], [[VALUE:%.*]] +; GFX11-NEXT: [[TMP2:%.*]] = bitcast double [[NEW]] to i64 +; GFX11-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64 +; GFX11-NEXT: [[TMP4:%.*]] = cmpxchg ptr addrspace(3) [[PTR]], i64 [[TMP3]], i64 [[TMP2]] monotonic monotonic, align 8 +; GFX11-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1 +; GFX11-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0 +; GFX11-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double +; GFX11-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]] +; GFX11: atomicrmw.end: +; GFX11-NEXT: ret double [[TMP5]] ; %ret = atomicrmw fadd ptr addrspace(3) %ptr, double %value monotonic, !amdgpu.ignore.denormal.mode !0 ret double %ret -- GitLab From 093171b053838020a30c7710015c56c88d51c7ef Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Mon, 22 Apr 2024 12:01:21 +0100 Subject: [PATCH 142/357] [Clang] Fix template alias default DWARF version (#89594) DW_TAG_template_alias DIEs were added in DWARFv4, not DWARFv5 --- clang/lib/Driver/ToolChains/Clang.cpp | 2 +- clang/test/Driver/debug-options.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 97b4aa1c9b1d..f8a81ee8ab56 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4634,7 +4634,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, // Emit DW_TAG_template_alias for template aliases? True by default for SCE. bool UseDebugTemplateAlias = - DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 5; + DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 4; if (const auto *DebugTemplateAlias = Args.getLastArg( options::OPT_gtemplate_alias, options::OPT_gno_template_alias)) { // DW_TAG_template_alias is only supported from DWARFv5 but if a user diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index b209c911d1ca..7d061410a229 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -456,9 +456,9 @@ // RUN: %clang -### -target x86_64 -c -g %s 2>&1 | FileCheck --check-prefix=FULL_TEMP_NAMES --implicit-check-not=debug-forward-template-params %s // FULL_TEMP_NAMES-NOT: -gsimple-template-names -//// Test -g[no-]template-alias (enabled by default with SCE debugger tuning and DWARFv5). +//// Test -g[no-]template-alias (enabled by default with SCE debugger tuning and DWARF version >= 4). // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS -// RUN: %clang -### -target x86_64 -c -gdwarf-4 -gsce %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS +// RUN: %clang -### -target x86_64 -c -gdwarf-3 -gsce %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce -gtemplate-alias %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce -gno-template-alias %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS // RUN: %clang -### -target x86_64 -c -gdwarf-5 -gtemplate-alias %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS -- GitLab From b7db392b687463e1f2815279e7dc4554b2ccb83f Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Mon, 22 Apr 2024 12:02:42 +0100 Subject: [PATCH 143/357] Fix DW_TAG_template_alias refs in llvm-dwarfdump --verify (#89589) A DW_TAG_template_alias referenced by a DW_AT_type incorrectly produces the error: error: DIE has DW_AT_type with incompatible tag DW_TAG_template_alias Fix and add test. --- llvm/include/llvm/BinaryFormat/Dwarf.def | 2 +- .../X86/verify_template_alias.yaml | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/llvm-dwarfdump/X86/verify_template_alias.yaml diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index 8cf90de637a3..460a9264536b 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -203,7 +203,7 @@ HANDLE_DW_TAG(0x0040, shared_type, 3, DWARF, DW_KIND_TYPE) // New in DWARF v4: HANDLE_DW_TAG(0x0041, type_unit, 4, DWARF, DW_KIND_NONE) HANDLE_DW_TAG(0x0042, rvalue_reference_type, 4, DWARF, DW_KIND_TYPE) -HANDLE_DW_TAG(0x0043, template_alias, 4, DWARF, DW_KIND_NONE) +HANDLE_DW_TAG(0x0043, template_alias, 4, DWARF, DW_KIND_TYPE) // New in DWARF v5: HANDLE_DW_TAG(0x0044, coarray_type, 5, DWARF, DW_KIND_TYPE) HANDLE_DW_TAG(0x0045, generic_subrange, 5, DWARF, DW_KIND_NONE) diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_template_alias.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_template_alias.yaml new file mode 100644 index 000000000000..e243c66c9aa6 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_template_alias.yaml @@ -0,0 +1,95 @@ +# RUN: yaml2obj %s | llvm-dwarfdump --verify - + +## Check --verify doesn't fail when a DW_AT_type references a +## DW_TAG_template_alias. +## +## $ cat test.cpp +## template +## using A = T; +## A a; +## +## $ clang++ test.cpp -g -gtemplate-alias -gsimple-template-names + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +DWARF: + debug_str: + - "clang version 19.0.0" + - "a" + - "A" + - "T" + - "bool" + debug_abbrev: + - Table: + - Code: 0x0000000000000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Code: 0x0000000000000002 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Code: 0x0000000000000003 + Tag: DW_TAG_template_alias + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x0000000000000004 + Tag: DW_TAG_template_type_parameter + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x0000000000000005 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + + debug_info: + - Version: 4 + AbbrOffset: 0x0000000000000000 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000000 + - Value: 0x0000000000000021 + - AbbrCode: 0x00000002 + Values: + - Value: 0x000000000000001b + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000017 + - Value: 0x0000000000000012 + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000019 + - Value: 0x0000000000000012 + - AbbrCode: 0x00000000 + Values: [] + - AbbrCode: 0x00000005 + Values: + - Value: 0x0000000000000015 + - Value: 0x0000000000000017 + - AbbrCode: 0x00000000 + Values: [] +... -- GitLab From a2692ac23f1421097f0d51c7325045ed38db6408 Mon Sep 17 00:00:00 2001 From: pvanhout Date: Mon, 22 Apr 2024 13:14:28 +0200 Subject: [PATCH 144/357] [llvm-split] Correctly deallocate TargetMachine Should fix the ASAN error. --- llvm/tools/llvm-split/llvm-split.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/tools/llvm-split/llvm-split.cpp b/llvm/tools/llvm-split/llvm-split.cpp index 41f392bcc531..39a89cb1d2e7 100644 --- a/llvm/tools/llvm-split/llvm-split.cpp +++ b/llvm/tools/llvm-split/llvm-split.cpp @@ -72,7 +72,7 @@ int main(int argc, char **argv) { cl::HideUnrelatedOptions({&SplitCategory, &getColorCategory()}); cl::ParseCommandLineOptions(argc, argv, "LLVM module splitter\n"); - TargetMachine *TM = nullptr; + std::unique_ptr TM; if (!MTriple.empty()) { InitializeAllTargets(); InitializeAllTargetMCs(); @@ -85,8 +85,8 @@ int main(int argc, char **argv) { } TargetOptions Options; - TM = T->createTargetMachine(MTriple, MCPU, /*FS*/ "", Options, std::nullopt, - std::nullopt); + TM = std::unique_ptr(T->createTargetMachine( + MTriple, MCPU, /*FS*/ "", Options, std::nullopt, std::nullopt)); } std::unique_ptr M = parseIRFile(InputFilename, Err, Context); -- GitLab From 10654e46d28ef0dd483a63dfc5e2bcfd9ea7e86a Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 22 Apr 2024 12:42:02 +0100 Subject: [PATCH 145/357] [KnownBitsTest] Common up isCorrect and isOptimal. NFC. (#89585) This de-duplicates the code that prints useful information when a test fails. --- llvm/unittests/Support/KnownBitsTest.cpp | 65 +++++++++--------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index feb0231300f1..2fa650c2c3bf 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -25,26 +25,20 @@ using BinaryBitsFn = using BinaryIntFn = llvm::function_ref(const APInt &, const APInt &)>; -static testing::AssertionResult isCorrect(const KnownBits &Exact, - const KnownBits &Computed, - ArrayRef Inputs) { - if (Computed.Zero.isSubsetOf(Exact.Zero) && - Computed.One.isSubsetOf(Exact.One)) - return testing::AssertionSuccess(); - - testing::AssertionResult Result = testing::AssertionFailure(); - Result << "Inputs = "; - for (const KnownBits &Input : Inputs) - Result << Input << ", "; - Result << "Computed = " << Computed << ", Exact = " << Exact; - return Result; -} - -static testing::AssertionResult isOptimal(const KnownBits &Exact, - const KnownBits &Computed, - ArrayRef Inputs) { - if (Computed == Exact) - return testing::AssertionSuccess(); +static testing::AssertionResult checkResult(const KnownBits &Exact, + const KnownBits &Computed, + ArrayRef Inputs, + bool CheckOptimality) { + if (CheckOptimality) { + // We generally don't want to return conflicting known bits, even if it is + // legal for always poison results. + if (Exact.hasConflict() || Computed == Exact) + return testing::AssertionSuccess(); + } else { + if (Computed.Zero.isSubsetOf(Exact.Zero) && + Computed.One.isSubsetOf(Exact.One)) + return testing::AssertionSuccess(); + } testing::AssertionResult Result = testing::AssertionFailure(); Result << "Inputs = "; @@ -71,12 +65,7 @@ static void testUnaryOpExhaustive(UnaryBitsFn BitsFn, UnaryIntFn IntFn, }); EXPECT_TRUE(!Computed.hasConflict()); - EXPECT_TRUE(isCorrect(Exact, Computed, Known)); - // We generally don't want to return conflicting known bits, even if it is - // legal for always poison results. - if (CheckOptimality && !Exact.hasConflict()) { - EXPECT_TRUE(isOptimal(Exact, Computed, Known)); - } + EXPECT_TRUE(checkResult(Exact, Computed, Known, CheckOptimality)); }); } } @@ -102,12 +91,8 @@ static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn, }); EXPECT_TRUE(!Computed.hasConflict()); - EXPECT_TRUE(isCorrect(Exact, Computed, {Known1, Known2})); - // We generally don't want to return conflicting known bits, even if it - // is legal for always poison results. - if (CheckOptimality && !Exact.hasConflict()) { - EXPECT_TRUE(isOptimal(Exact, Computed, {Known1, Known2})); - } + EXPECT_TRUE( + checkResult(Exact, Computed, {Known1, Known2}, CheckOptimality)); // In some cases we choose to return zero if the result is always // poison. if (RefinePoisonToZero && Exact.hasConflict()) { @@ -201,23 +186,23 @@ static void TestAddSubExhaustive(bool IsAdd) { KnownBits KnownComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/false, /*NUW=*/false, Known1, Known2); - EXPECT_TRUE(isOptimal(Known, KnownComputed, {Known1, Known2})); + EXPECT_TRUE(checkResult(Known, KnownComputed, {Known1, Known2}, + /*CheckOptimality=*/true)); KnownBits KnownNSWComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/true, /*NUW=*/false, Known1, Known2); - if (!KnownNSW.hasConflict()) - EXPECT_TRUE(isOptimal(KnownNSW, KnownNSWComputed, {Known1, Known2})); + EXPECT_TRUE(checkResult(KnownNSW, KnownNSWComputed, {Known1, Known2}, + /*CheckOptimality=*/true)); KnownBits KnownNUWComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/false, /*NUW=*/true, Known1, Known2); - if (!KnownNUW.hasConflict()) - EXPECT_TRUE(isOptimal(KnownNUW, KnownNUWComputed, {Known1, Known2})); + EXPECT_TRUE(checkResult(KnownNUW, KnownNUWComputed, {Known1, Known2}, + /*CheckOptimality=*/true)); KnownBits KnownNSWAndNUWComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/true, /*NUW=*/true, Known1, Known2); - if (!KnownNSWAndNUW.hasConflict()) - EXPECT_TRUE(isOptimal(KnownNSWAndNUW, KnownNSWAndNUWComputed, - {Known1, Known2})); + EXPECT_TRUE(checkResult(KnownNSWAndNUW, KnownNSWAndNUWComputed, + {Known1, Known2}, /*CheckOptimality=*/true)); }); }); } -- GitLab From c93f02978c33897615a312a85c6149911544ad63 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 22 Apr 2024 12:49:49 +0100 Subject: [PATCH 146/357] [VPlan] Remove custom checks for EVL placement in verifier (NFCI). After e2a72fa583d9, def-use chains of EVL are modeled explicitly. So there's no need for a custom check of its placement, as regular def-use verification will catch mis-placements. --- .../Transforms/Vectorize/VPlanVerifier.cpp | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp index 5587302207ac..7ebdb914fb85 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp @@ -92,50 +92,7 @@ static bool verifyVPBasicBlock(const VPBasicBlock *VPBB, for (const VPRecipeBase &R : *VPBB) RecipeNumbering[&R] = Cnt++; - // Set of recipe types along with VPInstruction Opcodes of all EVL-related - // recipes that must appear at most once in the header block. - DenseSet EVLFound; - const VPRecipeBase *VPWidenMemRecipe = nullptr; - const VPlan *Plan = VPBB->getPlan(); - bool IsHeader = Plan->getEntry()->getNumSuccessors() == 1 && - Plan->getVectorLoopRegion()->getEntry() == VPBB; - auto CheckEVLRecipiesInsts = [&](const VPRecipeBase *R) { - if (isa(R)) { - if (!IsHeader) { - errs() << "EVL PHI recipe not in entry block!\n"; - return false; - } - if (!EVLFound.insert(VPDef::VPEVLBasedIVPHISC).second) { - errs() << "EVL PHI recipe inserted more than once!\n"; - return false; - } - return true; - } - if (const auto *RInst = dyn_cast(R); - RInst && RInst->getOpcode() == VPInstruction::ExplicitVectorLength) { - if (!IsHeader) { - errs() << "EVL instruction not in the header block!\n"; - return false; - } - if (!EVLFound.insert(RInst->getOpcode() + VPDef::VPLastPHISC).second) { - errs() << "EVL instruction inserted more than once!\n"; - return false; - } - if (VPWidenMemRecipe) { - errs() << "Use of EVL instruction by widen memory recipe before " - "definition!\n"; - return false; - } - return true; - } - if (isa(R)) - VPWidenMemRecipe = R; - return true; - }; - for (const VPRecipeBase &R : *VPBB) { - if (!CheckEVLRecipiesInsts(&R)) - return false; for (const VPValue *V : R.definedValues()) { for (const VPUser *U : V->users()) { auto *UI = dyn_cast(U); -- GitLab From f0cbdd3e352a1d45965be686f48eee51159bb218 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 22 Apr 2024 12:54:48 +0100 Subject: [PATCH 147/357] [KnownBitsTest] Print name of function when exhaustive tests fail (#89588) When exhaustive unary/binary tests fail, print the name of the function being tested as well as the values of the inputs and outputs. Example of a simulated failure in testing "udiv exact": unittests/Support/KnownBitsTest.cpp:99: Failure Value of: checkResult(Name, Exact, Computed, {Known1, Known2}, CheckOptimality) Actual: false (udiv exact: Inputs = ???1, ????, Computed = ???1, Exact = 0???) Expected: true --- llvm/unittests/Support/KnownBitsTest.cpp | 106 +++++++++++++++-------- 1 file changed, 68 insertions(+), 38 deletions(-) diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 2fa650c2c3bf..b970137e63b7 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -10,9 +10,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/KnownBits.h" #include "KnownBitsTest.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "gtest/gtest.h" using namespace llvm; @@ -25,7 +27,7 @@ using BinaryBitsFn = using BinaryIntFn = llvm::function_ref(const APInt &, const APInt &)>; -static testing::AssertionResult checkResult(const KnownBits &Exact, +static testing::AssertionResult checkResult(Twine Name, const KnownBits &Exact, const KnownBits &Computed, ArrayRef Inputs, bool CheckOptimality) { @@ -41,6 +43,7 @@ static testing::AssertionResult checkResult(const KnownBits &Exact, } testing::AssertionResult Result = testing::AssertionFailure(); + Result << Name << ": "; Result << "Inputs = "; for (const KnownBits &Input : Inputs) Result << Input << ", "; @@ -48,7 +51,8 @@ static testing::AssertionResult checkResult(const KnownBits &Exact, return Result; } -static void testUnaryOpExhaustive(UnaryBitsFn BitsFn, UnaryIntFn IntFn, +static void testUnaryOpExhaustive(StringRef Name, UnaryBitsFn BitsFn, + UnaryIntFn IntFn, bool CheckOptimality = true) { for (unsigned Bits : {1, 4}) { ForeachKnownBits(Bits, [&](const KnownBits &Known) { @@ -65,12 +69,13 @@ static void testUnaryOpExhaustive(UnaryBitsFn BitsFn, UnaryIntFn IntFn, }); EXPECT_TRUE(!Computed.hasConflict()); - EXPECT_TRUE(checkResult(Exact, Computed, Known, CheckOptimality)); + EXPECT_TRUE(checkResult(Name, Exact, Computed, Known, CheckOptimality)); }); } } -static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn, +static void testBinaryOpExhaustive(StringRef Name, BinaryBitsFn BitsFn, + BinaryIntFn IntFn, bool CheckOptimality = true, bool RefinePoisonToZero = false) { for (unsigned Bits : {1, 4}) { @@ -91,8 +96,8 @@ static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn, }); EXPECT_TRUE(!Computed.hasConflict()); - EXPECT_TRUE( - checkResult(Exact, Computed, {Known1, Known2}, CheckOptimality)); + EXPECT_TRUE(checkResult(Name, Exact, Computed, {Known1, Known2}, + CheckOptimality)); // In some cases we choose to return zero if the result is always // poison. if (RefinePoisonToZero && Exact.hasConflict()) { @@ -137,6 +142,7 @@ TEST(KnownBitsTest, AddCarryExhaustive) { } static void TestAddSubExhaustive(bool IsAdd) { + Twine Name = IsAdd ? "add" : "sub"; unsigned Bits = 4; ForeachKnownBits(Bits, [&](const KnownBits &Known1) { ForeachKnownBits(Bits, [&](const KnownBits &Known2) { @@ -186,23 +192,26 @@ static void TestAddSubExhaustive(bool IsAdd) { KnownBits KnownComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/false, /*NUW=*/false, Known1, Known2); - EXPECT_TRUE(checkResult(Known, KnownComputed, {Known1, Known2}, + EXPECT_TRUE(checkResult(Name, Known, KnownComputed, {Known1, Known2}, /*CheckOptimality=*/true)); KnownBits KnownNSWComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/true, /*NUW=*/false, Known1, Known2); - EXPECT_TRUE(checkResult(KnownNSW, KnownNSWComputed, {Known1, Known2}, + EXPECT_TRUE(checkResult(Name + " nsw", KnownNSW, KnownNSWComputed, + {Known1, Known2}, /*CheckOptimality=*/true)); KnownBits KnownNUWComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/false, /*NUW=*/true, Known1, Known2); - EXPECT_TRUE(checkResult(KnownNUW, KnownNUWComputed, {Known1, Known2}, + EXPECT_TRUE(checkResult(Name + " nuw", KnownNUW, KnownNUWComputed, + {Known1, Known2}, /*CheckOptimality=*/true)); KnownBits KnownNSWAndNUWComputed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/true, /*NUW=*/true, Known1, Known2); - EXPECT_TRUE(checkResult(KnownNSWAndNUW, KnownNSWAndNUWComputed, - {Known1, Known2}, /*CheckOptimality=*/true)); + EXPECT_TRUE(checkResult(Name + " nsw nuw", KnownNSWAndNUW, + KnownNSWAndNUWComputed, {Known1, Known2}, + /*CheckOptimality=*/true)); }); }); } @@ -267,27 +276,31 @@ TEST(KnownBitsTest, SignBitUnknown) { TEST(KnownBitsTest, BinaryExhaustive) { testBinaryOpExhaustive( + "and", [](const KnownBits &Known1, const KnownBits &Known2) { return Known1 & Known2; }, [](const APInt &N1, const APInt &N2) { return N1 & N2; }); testBinaryOpExhaustive( + "or", [](const KnownBits &Known1, const KnownBits &Known2) { return Known1 | Known2; }, [](const APInt &N1, const APInt &N2) { return N1 | N2; }); testBinaryOpExhaustive( + "xor", [](const KnownBits &Known1, const KnownBits &Known2) { return Known1 ^ Known2; }, [](const APInt &N1, const APInt &N2) { return N1 ^ N2; }); - testBinaryOpExhaustive(KnownBits::umax, APIntOps::umax); - testBinaryOpExhaustive(KnownBits::umin, APIntOps::umin); - testBinaryOpExhaustive(KnownBits::smax, APIntOps::smax); - testBinaryOpExhaustive(KnownBits::smin, APIntOps::smin); - testBinaryOpExhaustive(KnownBits::abdu, APIntOps::abdu); - testBinaryOpExhaustive(KnownBits::abds, APIntOps::abds); + testBinaryOpExhaustive("umax", KnownBits::umax, APIntOps::umax); + testBinaryOpExhaustive("umin", KnownBits::umin, APIntOps::umin); + testBinaryOpExhaustive("smax", KnownBits::smax, APIntOps::smax); + testBinaryOpExhaustive("smin", KnownBits::smin, APIntOps::smin); + testBinaryOpExhaustive("abdu", KnownBits::abdu, APIntOps::abdu); + testBinaryOpExhaustive("abds", KnownBits::abds, APIntOps::abds); testBinaryOpExhaustive( + "udiv", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::udiv(Known1, Known2); }, @@ -298,6 +311,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/false); testBinaryOpExhaustive( + "udiv exact", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::udiv(Known1, Known2, /*Exact*/ true); }, @@ -308,6 +322,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/false); testBinaryOpExhaustive( + "sdiv", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::sdiv(Known1, Known2); }, @@ -318,6 +333,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/false); testBinaryOpExhaustive( + "sdiv exact", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::sdiv(Known1, Known2, /*Exact*/ true); }, @@ -329,7 +345,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::urem, + "urem", KnownBits::urem, [](const APInt &N1, const APInt &N2) -> std::optional { if (N2.isZero()) return std::nullopt; @@ -337,7 +353,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::srem, + "srem", KnownBits::srem, [](const APInt &N1, const APInt &N2) -> std::optional { if (N2.isZero()) return std::nullopt; @@ -345,30 +361,31 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::sadd_sat, + "sadd_sat", KnownBits::sadd_sat, [](const APInt &N1, const APInt &N2) -> std::optional { return N1.sadd_sat(N2); }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::uadd_sat, + "uadd_sat", KnownBits::uadd_sat, [](const APInt &N1, const APInt &N2) -> std::optional { return N1.uadd_sat(N2); }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::ssub_sat, + "ssub_sat", KnownBits::ssub_sat, [](const APInt &N1, const APInt &N2) -> std::optional { return N1.ssub_sat(N2); }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::usub_sat, + "usub_sat", KnownBits::usub_sat, [](const APInt &N1, const APInt &N2) -> std::optional { return N1.usub_sat(N2); }, /*CheckOptimality=*/false); testBinaryOpExhaustive( + "shl", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::shl(Known1, Known2); }, @@ -379,6 +396,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "ushl_ov", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::shl(Known1, Known2, /* NUW */ true); }, @@ -391,6 +409,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "shl nsw", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::shl(Known1, Known2, /* NUW */ false, /* NSW */ true); }, @@ -403,6 +422,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "shl nuw", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::shl(Known1, Known2, /* NUW */ true, /* NSW */ true); }, @@ -417,6 +437,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "lshr", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::lshr(Known1, Known2); }, @@ -427,6 +448,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "lshr exact", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::lshr(Known1, Known2, /*ShAmtNonZero=*/false, /*Exact=*/true); @@ -440,6 +462,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "ashr", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::ashr(Known1, Known2); }, @@ -450,6 +473,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "ashr exact", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::ashr(Known1, Known2, /*ShAmtNonZero=*/false, /*Exact=*/true); @@ -463,38 +487,44 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, /*CheckOptimality=*/true, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( + "mul", [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::mul(Known1, Known2); }, [](const APInt &N1, const APInt &N2) { return N1 * N2; }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::mulhs, + "mulhs", KnownBits::mulhs, [](const APInt &N1, const APInt &N2) { return APIntOps::mulhs(N1, N2); }, /*CheckOptimality=*/false); testBinaryOpExhaustive( - KnownBits::mulhu, + "mulhu", KnownBits::mulhu, [](const APInt &N1, const APInt &N2) { return APIntOps::mulhu(N1, N2); }, /*CheckOptimality=*/false); } TEST(KnownBitsTest, UnaryExhaustive) { - testUnaryOpExhaustive([](const KnownBits &Known) { return Known.abs(); }, - [](const APInt &N) { return N.abs(); }); + testUnaryOpExhaustive( + "abs", [](const KnownBits &Known) { return Known.abs(); }, + [](const APInt &N) { return N.abs(); }); - testUnaryOpExhaustive([](const KnownBits &Known) { return Known.abs(true); }, - [](const APInt &N) -> std::optional { - if (N.isMinSignedValue()) - return std::nullopt; - return N.abs(); - }); + testUnaryOpExhaustive( + "abs(true)", [](const KnownBits &Known) { return Known.abs(true); }, + [](const APInt &N) -> std::optional { + if (N.isMinSignedValue()) + return std::nullopt; + return N.abs(); + }); - testUnaryOpExhaustive([](const KnownBits &Known) { return Known.blsi(); }, - [](const APInt &N) { return N & -N; }); - testUnaryOpExhaustive([](const KnownBits &Known) { return Known.blsmsk(); }, - [](const APInt &N) { return N ^ (N - 1); }); + testUnaryOpExhaustive( + "blsi", [](const KnownBits &Known) { return Known.blsi(); }, + [](const APInt &N) { return N & -N; }); + testUnaryOpExhaustive( + "blsmsk", [](const KnownBits &Known) { return Known.blsmsk(); }, + [](const APInt &N) { return N ^ (N - 1); }); testUnaryOpExhaustive( + "mul self", [](const KnownBits &Known) { return KnownBits::mul(Known, Known, /*SelfMultiply*/ true); }, -- GitLab From e4f7c524d7f3efa1e819ca2e2d835c8f4c5765f4 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 22 Apr 2024 14:09:14 +0200 Subject: [PATCH 148/357] AMDGPU: Refactor atomicrmw fadd expansion logic (NFC) (#89469) This had some repeated and overlapping conditions, which made it more difficult to handle the new metadata scheme. Reflow the function to handle the easy LDS cases first. For the flat/global cases, write in a positive-enabled style where everything unhandled hits a default cmpxchg. Depends #89468 --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 54 ++++++++++------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 12b7f05c4463..17b6e0cb9c3b 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -16075,40 +16075,37 @@ SITargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { return AtomicExpansionKind::CmpXChg; } - if (!Ty->isFloatTy() && (!Subtarget->hasGFX90AInsts() || !Ty->isDoubleTy())) + if (!AMDGPU::isFlatGlobalAddrSpace(AS) && + AS != AMDGPUAS::BUFFER_FAT_POINTER) return AtomicExpansionKind::CmpXChg; - if ((AMDGPU::isFlatGlobalAddrSpace(AS) || - AS == AMDGPUAS::BUFFER_FAT_POINTER) && - Subtarget->hasAtomicFaddNoRtnInsts()) { - if (Subtarget->hasGFX940Insts()) - return AtomicExpansionKind::None; + // TODO: gfx940 supports v2f16 and v2bf16 + if (Subtarget->hasGFX940Insts() && (Ty->isFloatTy() || Ty->isDoubleTy())) + return AtomicExpansionKind::None; - if (unsafeFPAtomicsDisabled(RMW->getFunction())) - return AtomicExpansionKind::CmpXChg; + if (unsafeFPAtomicsDisabled(RMW->getFunction())) + return AtomicExpansionKind::CmpXChg; - // Always expand system scope fp atomics. - if (HasSystemScope) - return AtomicExpansionKind::CmpXChg; + // Always expand system scope fp atomics. + if (HasSystemScope) + return AtomicExpansionKind::CmpXChg; - if ((AMDGPU::isExtendedGlobalAddrSpace(AS) || - AS == AMDGPUAS::BUFFER_FAT_POINTER) && - Ty->isFloatTy()) { - // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx940, gfx11+. - if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts()) - return ReportUnsafeHWInst(AtomicExpansionKind::None); - // global/buffer atomic fadd f32 rtn: gfx90a, gfx940, gfx11+. - if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts()) - return ReportUnsafeHWInst(AtomicExpansionKind::None); - } + // global and flat atomic fadd f64: gfx90a, gfx940. + if (Subtarget->hasGFX90AInsts() && Ty->isDoubleTy()) + return ReportUnsafeHWInst(AtomicExpansionKind::None); - // flat atomic fadd f32: gfx940, gfx11+. - if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy() && - Subtarget->hasFlatAtomicFaddF32Inst()) + if (AS != AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) { + // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx940, gfx11+. + if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts()) + return ReportUnsafeHWInst(AtomicExpansionKind::None); + // global/buffer atomic fadd f32 rtn: gfx90a, gfx940, gfx11+. + if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts()) return ReportUnsafeHWInst(AtomicExpansionKind::None); + } - // global and flat atomic fadd f64: gfx90a, gfx940. - if (Ty->isDoubleTy() && Subtarget->hasGFX90AInsts()) + // flat atomic fadd f32: gfx940, gfx11+. + if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) { + if (Subtarget->hasFlatAtomicFaddF32Inst()) return ReportUnsafeHWInst(AtomicExpansionKind::None); // If it is in flat address space, and the type is float, we will try to @@ -16116,15 +16113,12 @@ SITargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { // reason we need that is, in the expansion, we emit the check of address // space. If it is in global address space, we emit the global atomic // fadd; if it is in shared address space, we emit the LDS atomic fadd. - if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy() && - Subtarget->hasLDSFPAtomicAddF32()) { + if (Subtarget->hasLDSFPAtomicAddF32()) { if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts()) return AtomicExpansionKind::Expand; if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts()) return AtomicExpansionKind::Expand; } - - return AtomicExpansionKind::CmpXChg; } return AtomicExpansionKind::CmpXChg; -- GitLab From 2e7bd22b37cd6f4e266d0512220b983144d9be0b Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Mon, 22 Apr 2024 07:19:25 -0500 Subject: [PATCH 149/357] [NFC] Fix comments in PassBuilder functions (#89513) The original comments mention `addPreLinkLTODefaultPipeline`, but I could not find any functions with this name, even in https://reviews.llvm.org/D33540 (8b3be4e59d861130746206e41ae42c918bc165df) where this comment was added. I assume they meant to refer to `buildThinLTOPreLinkDefaultPipeline` and `buildLTOPreLinkDefaultPipeline` and so this patch uses them. --- llvm/include/llvm/Passes/PassBuilder.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index c8f643452bb1..9b4da1c466f5 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -264,12 +264,12 @@ public: /// the LTO run. ModulePassManager buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level); - /// Build an ThinLTO default optimization pipeline to a pass manager. + /// Build a ThinLTO default optimization pipeline to a pass manager. /// /// This provides a good default optimization pipeline for link-time /// optimization and code generation. It is particularly tuned to fit well /// when IR coming into the LTO phase was first run through \c - /// addPreLinkLTODefaultPipeline, and the two coordinate closely. + /// buildThinLTOPreLinkDefaultPipeline, and the two coordinate closely. ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary); @@ -288,7 +288,7 @@ public: /// This provides a good default optimization pipeline for link-time /// optimization and code generation. It is particularly tuned to fit well /// when IR coming into the LTO phase was first run through \c - /// addPreLinkLTODefaultPipeline, and the two coordinate closely. + /// buildLTOPreLinkDefaultPipeline, and the two coordinate closely. ModulePassManager buildLTODefaultPipeline(OptimizationLevel Level, ModuleSummaryIndex *ExportSummary); -- GitLab From 5597d97e9982d8f87c9226898f90c5875b498f71 Mon Sep 17 00:00:00 2001 From: aniplcc Date: Mon, 22 Apr 2024 18:01:55 +0530 Subject: [PATCH 150/357] [clang] MveEmitter: Pass Args as a const reference (#89551) Closes #89192. --- clang/utils/TableGen/MveEmitter.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 88e7b6e85465..c455071ed9da 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -658,9 +658,9 @@ public: std::vector Args; std::set AddressArgs; std::map IntegerArgs; - IRBuilderResult(StringRef CallPrefix, std::vector Args, - std::set AddressArgs, - std::map IntegerArgs) + IRBuilderResult(StringRef CallPrefix, const std::vector &Args, + const std::set &AddressArgs, + const std::map &IntegerArgs) : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs), IntegerArgs(IntegerArgs) {} void genCode(raw_ostream &OS, @@ -727,8 +727,9 @@ public: std::string IntrinsicID; std::vector ParamTypes; std::vector Args; - IRIntrinsicResult(StringRef IntrinsicID, std::vector ParamTypes, - std::vector Args) + IRIntrinsicResult(StringRef IntrinsicID, + const std::vector &ParamTypes, + const std::vector &Args) : IntrinsicID(std::string(IntrinsicID)), ParamTypes(ParamTypes), Args(Args) {} void genCode(raw_ostream &OS, -- GitLab From 8e45935824a905dec7739ea8c95af5fdf2c0c123 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 22 Apr 2024 13:37:06 +0100 Subject: [PATCH 151/357] [RemoveDIs] Make verify-uselistorder preserve the input debug info format (#87789) Verify-uselistorder wants to take some input IR and verify that the uselist order is stable after roundtripping to bitcode and assembly. This is disrupted if the file is converted between the new and old debug info formats after parsing - while there's no functional difference, the change to the in-memory representation of the IR modifies the uselist. This patch changes verify-uselistorder to not convert input files between debug info formats by default, preventing changes from being made to the file being checked. In addition, this patch makes it so that when we _do_ print IR in the new debug info format to bitcode or assembly, we delete any lingering debug intrinsic declarations, ensuring that we don't write uselist entries for them. --- llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp | 4 +++ .../Transforms/IPO/ThinLTOBitcodeWriter.cpp | 4 +-- llvm/tools/llvm-as/llvm-as.cpp | 4 ++- llvm/tools/llvm-dis/llvm-dis.cpp | 2 ++ llvm/tools/llvm-link/llvm-link.cpp | 12 +++++++- .../verify-uselistorder.cpp | 29 +++++++++---------- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp index 4f2486c963e9..5f66e1ea0a83 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp @@ -23,6 +23,8 @@ extern bool WriteNewDbgInfoFormatToBitcode; PreservedAnalyses BitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { ScopedDbgInfoFormatSetter FormatSetter(M, M.IsNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode); + if (M.IsNewDbgInfoFormat) + M.removeDebugIntrinsicDeclarations(); const ModuleSummaryIndex *Index = EmitSummaryIndex ? &(AM.getResult(M)) @@ -54,6 +56,8 @@ namespace { bool runOnModule(Module &M) override { ScopedDbgInfoFormatSetter FormatSetter( M, M.IsNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode); + if (M.IsNewDbgInfoFormat) + M.removeDebugIntrinsicDeclarations(); WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder, /*Index=*/nullptr, /*EmitModuleHash=*/false); diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 4df18c824927..9bf29c46938e 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -581,10 +581,10 @@ llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { FunctionAnalysisManager &FAM = AM.getResult(M).getManager(); - // RemoveDIs: there's no bitcode representation of the DbgVariableRecord - // debug-info, convert to dbg.values before writing out. ScopedDbgInfoFormatSetter FormatSetter(M, M.IsNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode); + if (M.IsNewDbgInfoFormat) + M.removeDebugIntrinsicDeclarations(); bool Changed = writeThinLTOBitcode( OS, ThinLinkOS, diff --git a/llvm/tools/llvm-as/llvm-as.cpp b/llvm/tools/llvm-as/llvm-as.cpp index fd852563838f..e48e3f4d22c1 100644 --- a/llvm/tools/llvm-as/llvm-as.cpp +++ b/llvm/tools/llvm-as/llvm-as.cpp @@ -143,8 +143,10 @@ int main(int argc, char **argv) { // Convert to new debug format if requested. assert(!M->IsNewDbgInfoFormat && "Unexpectedly in new debug mode"); - if (UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode) + if (UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode) { M->convertToNewDbgValues(); + M->removeDebugIntrinsicDeclarations(); + } std::unique_ptr Index = std::move(ModuleAndIndex.Index); diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp index 6ad1c99568e4..fbbb5506e43e 100644 --- a/llvm/tools/llvm-dis/llvm-dis.cpp +++ b/llvm/tools/llvm-dis/llvm-dis.cpp @@ -259,6 +259,8 @@ int main(int argc, char **argv) { if (!DontPrint) { if (M) { ScopedDbgInfoFormatSetter FormatSetter(*M, WriteNewDbgInfoFormat); + if (WriteNewDbgInfoFormat) + M->removeDebugIntrinsicDeclarations(); M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); } if (Index) diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 8f80cc26f316..7794f2d81ed0 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -136,6 +136,8 @@ static cl::opt TryUseNewDbgInfoFormat( extern cl::opt UseNewDbgInfoFormat; extern cl::opt PreserveInputDbgFormat; +extern cl::opt WriteNewDbgInfoFormat; +extern bool WriteNewDbgInfoFormatToBitcode; extern cl::opt LoadBitcodeIntoNewDbgInfoFormat; @@ -545,10 +547,18 @@ int main(int argc, char **argv) { if (Verbose) errs() << "Writing bitcode...\n"; + auto SetFormat = [&](bool NewFormat) { + Composite->setIsNewDbgInfoFormat(NewFormat); + if (NewFormat) + Composite->removeDebugIntrinsicDeclarations(); + }; if (OutputAssembly) { + SetFormat(WriteNewDbgInfoFormat); Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder); - } else if (Force || !CheckBitcodeOutputToConsole(Out.os())) + } else if (Force || !CheckBitcodeOutputToConsole(Out.os())) { + SetFormat(WriteNewDbgInfoFormatToBitcode); WriteBitcodeToFile(*Composite, Out.os(), PreserveBitcodeUseListOrder); + } // Declare success. Out.keep(); diff --git a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp index cb07dede1d13..84fc777e1fdf 100644 --- a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp +++ b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp @@ -68,7 +68,7 @@ static cl::opt cl::desc("Number of times to shuffle and verify use-lists"), cl::init(1), cl::cat(Cat)); -extern cl::opt LoadBitcodeIntoNewDbgInfoFormat; +extern cl::opt PreserveInputDbgFormat; namespace { @@ -169,9 +169,6 @@ std::unique_ptr TempFile::readBitcode(LLVMContext &Context) const { return nullptr; } - // verify-uselistoder currently only supports old-style debug info mode. - // FIXME: Update mapping code for RemoveDIs. - ModuleOr.get()->setIsNewDbgInfoFormat(false); return std::move(ModuleOr.get()); } @@ -181,9 +178,6 @@ std::unique_ptr TempFile::readAssembly(LLVMContext &Context) const { std::unique_ptr M = parseAssemblyFile(Filename, Err, Context); if (!M.get()) Err.print("verify-uselistorder", errs()); - // verify-uselistoder currently only supports old-style debug info mode. - // FIXME: Update mapping code for RemoveDIs. - M->setIsNewDbgInfoFormat(false); return M; } @@ -228,8 +222,15 @@ ValueMapping::ValueMapping(const Module &M) { map(&I); // Constants used by instructions. - for (const BasicBlock &BB : F) - for (const Instruction &I : BB) + for (const BasicBlock &BB : F) { + for (const Instruction &I : BB) { + for (const DbgVariableRecord &DVR : + filterDbgVars(I.getDbgRecordRange())) { + for (Value *Op : DVR.location_ops()) + map(Op); + if (DVR.isDbgAssign()) + map(DVR.getAddress()); + } for (const Value *Op : I.operands()) { // Look through a metadata wrapper. if (const auto *MAV = dyn_cast(Op)) @@ -240,6 +241,8 @@ ValueMapping::ValueMapping(const Module &M) { isa(Op)) map(Op); } + } + } } } @@ -536,6 +539,7 @@ static void reverseUseLists(Module &M) { } int main(int argc, char **argv) { + PreserveInputDbgFormat = cl::boolOrDefault::BOU_TRUE; InitLLVM X(argc, argv); // Enable debug stream buffering. @@ -545,18 +549,11 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm tool to verify use-list order\n"); - // Do not load bitcode into the new debug info format by default. - if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) - LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_FALSE; - LLVMContext Context; SMDiagnostic Err; // Load the input module... std::unique_ptr M = parseIRFile(InputFilename, Err, Context); - // verify-uselistoder currently only supports old-style debug info mode. - // FIXME: Update mapping code for RemoveDIs. - M->setIsNewDbgInfoFormat(false); if (!M.get()) { Err.print(argv[0], errs()); -- GitLab From 103f1be76fbb82ef8ed95b6112d914d4996e27be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 11:11:11 +0200 Subject: [PATCH 152/357] [clang][Interp][NFC] getRecord() might return null --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 5b9ef9980c9c..d406ac332ae2 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1351,6 +1351,8 @@ bool ByteCodeExprGen::VisitMemberExpr(const MemberExpr *E) { if (const auto *FD = dyn_cast(Member)) { const RecordDecl *RD = FD->getParent(); const Record *R = getRecord(RD); + if (!R) + return false; const Record::Field *F = R->getField(FD); // Leave a pointer to the field on the stack. if (F->Decl->getType()->isReferenceType()) -- GitLab From 15883684a72cf6c64d856a11f8cd10b3a332dbcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 11:34:05 +0200 Subject: [PATCH 153/357] [clang][Interp] Fix casting pointers to int128 --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 6 ++++++ clang/lib/AST/Interp/Interp.h | 26 ++++++++++++++++++++++++ clang/lib/AST/Interp/Opcodes.td | 13 ++++++++++-- clang/test/AST/Interp/c.c | 6 ++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index d406ac332ae2..8cd0c198d9a8 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -194,6 +194,12 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return false; PrimType T = classifyPrim(CE->getType()); + if (T == PT_IntAP) + return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()), + CE); + if (T == PT_IntAPS) + return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()), + CE); return this->emitCastPointerIntegral(T, CE); } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index cebedf59e059..d593d764d85a 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1833,6 +1833,32 @@ bool CastPointerIntegral(InterpState &S, CodePtr OpPC) { return true; } +static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, + uint32_t BitWidth) { + const Pointer &Ptr = S.Stk.pop(); + + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + + S.Stk.push>( + IntegralAP::from(Ptr.getIntegerRepresentation(), BitWidth)); + return true; +} + +static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, + uint32_t BitWidth) { + const Pointer &Ptr = S.Stk.pop(); + + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + + S.Stk.push>( + IntegralAP::from(Ptr.getIntegerRepresentation(), BitWidth)); + return true; +} + //===----------------------------------------------------------------------===// // Zero, Nullptr //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index e17be3afd257..0a6c976f9b5b 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -664,10 +664,19 @@ def CastFloatingIntegralAPS : Opcode { } def CastPointerIntegral : Opcode { - let Types = [AluTypeClass]; - let Args = []; + let Types = [FixedSizeIntegralTypeClass]; let HasGroup = 1; } +def CastPointerIntegralAP : Opcode { + let Types = []; + let HasGroup = 0; + let Args = [ArgUint32]; +} +def CastPointerIntegralAPS : Opcode { + let Types = []; + let HasGroup = 0; + let Args = [ArgUint32]; +} def DecayPtr : Opcode { let Types = [PtrTypeClass, PtrTypeClass]; diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 5ae9b1dc7bff..a5951158ed0e 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -257,3 +257,9 @@ int Y __attribute__((annotate( 42, (struct TestStruct) { .a = 1, .b = 2 } ))); + +#ifdef __SIZEOF_INT128__ +const int *p = &b; +const __int128 K = (__int128)(int*)0; +const unsigned __int128 KU = (unsigned __int128)(int*)0; +#endif -- GitLab From 346d2c0268a552abecdc9b7f7a4da860dc4235a5 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 22 Apr 2024 13:41:25 +0100 Subject: [PATCH 154/357] [KnownBitsTest] Standardize variable names in exhaustive tests --- llvm/unittests/Support/KnownBitsTest.cpp | 82 ++++++++++++------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index b970137e63b7..d74070702716 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -117,9 +117,9 @@ TEST(KnownBitsTest, AddCarryExhaustive) { ForeachKnownBits(1, [&](const KnownBits &KnownCarry) { // Explicitly compute known bits of the addition by trying all // possibilities. - KnownBits Known(Bits); - Known.Zero.setAllBits(); - Known.One.setAllBits(); + KnownBits Exact(Bits); + Exact.Zero.setAllBits(); + Exact.One.setAllBits(); ForeachNumInKnownBits(Known1, [&](const APInt &N1) { ForeachNumInKnownBits(Known2, [&](const APInt &N2) { ForeachNumInKnownBits(KnownCarry, [&](const APInt &Carry) { @@ -127,15 +127,15 @@ TEST(KnownBitsTest, AddCarryExhaustive) { if (Carry.getBoolValue()) ++Add; - Known.One &= Add; - Known.Zero &= ~Add; + Exact.One &= Add; + Exact.Zero &= ~Add; }); }); }); - KnownBits KnownComputed = + KnownBits Computed = KnownBits::computeForAddCarry(Known1, Known2, KnownCarry); - EXPECT_EQ(Known, KnownComputed); + EXPECT_EQ(Exact, Computed); }); }); }); @@ -146,16 +146,16 @@ static void TestAddSubExhaustive(bool IsAdd) { unsigned Bits = 4; ForeachKnownBits(Bits, [&](const KnownBits &Known1) { ForeachKnownBits(Bits, [&](const KnownBits &Known2) { - KnownBits Known(Bits), KnownNSW(Bits), KnownNUW(Bits), - KnownNSWAndNUW(Bits); - Known.Zero.setAllBits(); - Known.One.setAllBits(); - KnownNSW.Zero.setAllBits(); - KnownNSW.One.setAllBits(); - KnownNUW.Zero.setAllBits(); - KnownNUW.One.setAllBits(); - KnownNSWAndNUW.Zero.setAllBits(); - KnownNSWAndNUW.One.setAllBits(); + KnownBits Exact(Bits), ExactNSW(Bits), ExactNUW(Bits), + ExactNSWAndNUW(Bits); + Exact.Zero.setAllBits(); + Exact.One.setAllBits(); + ExactNSW.Zero.setAllBits(); + ExactNSW.One.setAllBits(); + ExactNUW.Zero.setAllBits(); + ExactNUW.One.setAllBits(); + ExactNSWAndNUW.Zero.setAllBits(); + ExactNSWAndNUW.One.setAllBits(); ForeachNumInKnownBits(Known1, [&](const APInt &N1) { ForeachNumInKnownBits(Known2, [&](const APInt &N2) { @@ -170,47 +170,47 @@ static void TestAddSubExhaustive(bool IsAdd) { Res = N1.ssub_ov(N2, SignedOverflow); } - Known.One &= Res; - Known.Zero &= ~Res; + Exact.One &= Res; + Exact.Zero &= ~Res; if (!SignedOverflow) { - KnownNSW.One &= Res; - KnownNSW.Zero &= ~Res; + ExactNSW.One &= Res; + ExactNSW.Zero &= ~Res; } if (!UnsignedOverflow) { - KnownNUW.One &= Res; - KnownNUW.Zero &= ~Res; + ExactNUW.One &= Res; + ExactNUW.Zero &= ~Res; } if (!UnsignedOverflow && !SignedOverflow) { - KnownNSWAndNUW.One &= Res; - KnownNSWAndNUW.Zero &= ~Res; + ExactNSWAndNUW.One &= Res; + ExactNSWAndNUW.Zero &= ~Res; } }); }); - KnownBits KnownComputed = KnownBits::computeForAddSub( + KnownBits Computed = KnownBits::computeForAddSub( IsAdd, /*NSW=*/false, /*NUW=*/false, Known1, Known2); - EXPECT_TRUE(checkResult(Name, Known, KnownComputed, {Known1, Known2}, + EXPECT_TRUE(checkResult(Name, Exact, Computed, {Known1, Known2}, /*CheckOptimality=*/true)); - KnownBits KnownNSWComputed = KnownBits::computeForAddSub( + KnownBits ComputedNSW = KnownBits::computeForAddSub( IsAdd, /*NSW=*/true, /*NUW=*/false, Known1, Known2); - EXPECT_TRUE(checkResult(Name + " nsw", KnownNSW, KnownNSWComputed, + EXPECT_TRUE(checkResult(Name + " nsw", ExactNSW, ComputedNSW, {Known1, Known2}, /*CheckOptimality=*/true)); - KnownBits KnownNUWComputed = KnownBits::computeForAddSub( + KnownBits ComputedNUW = KnownBits::computeForAddSub( IsAdd, /*NSW=*/false, /*NUW=*/true, Known1, Known2); - EXPECT_TRUE(checkResult(Name + " nuw", KnownNUW, KnownNUWComputed, + EXPECT_TRUE(checkResult(Name + " nuw", ExactNUW, ComputedNUW, {Known1, Known2}, /*CheckOptimality=*/true)); - KnownBits KnownNSWAndNUWComputed = KnownBits::computeForAddSub( + KnownBits ComputedNSWAndNUW = KnownBits::computeForAddSub( IsAdd, /*NSW=*/true, /*NUW=*/true, Known1, Known2); - EXPECT_TRUE(checkResult(Name + " nsw nuw", KnownNSWAndNUW, - KnownNSWAndNUWComputed, {Known1, Known2}, + EXPECT_TRUE(checkResult(Name + " nsw nuw", ExactNSWAndNUW, + ComputedNSWAndNUW, {Known1, Known2}, /*CheckOptimality=*/true)); }); }); @@ -228,9 +228,9 @@ TEST(KnownBitsTest, SubBorrowExhaustive) { ForeachKnownBits(1, [&](const KnownBits &KnownBorrow) { // Explicitly compute known bits of the subtraction by trying all // possibilities. - KnownBits Known(Bits); - Known.Zero.setAllBits(); - Known.One.setAllBits(); + KnownBits Exact(Bits); + Exact.Zero.setAllBits(); + Exact.One.setAllBits(); ForeachNumInKnownBits(Known1, [&](const APInt &N1) { ForeachNumInKnownBits(Known2, [&](const APInt &N2) { ForeachNumInKnownBits(KnownBorrow, [&](const APInt &Borrow) { @@ -238,15 +238,15 @@ TEST(KnownBitsTest, SubBorrowExhaustive) { if (Borrow.getBoolValue()) --Sub; - Known.One &= Sub; - Known.Zero &= ~Sub; + Exact.One &= Sub; + Exact.Zero &= ~Sub; }); }); }); - KnownBits KnownComputed = + KnownBits Computed = KnownBits::computeForSubBorrow(Known1, Known2, KnownBorrow); - EXPECT_EQ(Known, KnownComputed); + EXPECT_EQ(Exact, Computed); }); }); }); -- GitLab From e2754890ca75d64b3acb9b8655874421aed8f9cb Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 22 Apr 2024 08:45:02 -0400 Subject: [PATCH 155/357] [libc++] Don't commit libcxx.imp (#89391) We can instead generate it on-the-fly when we install the headers. This reduces the amount of boilerplate we have to re-generate whenever we add, remove or relocate header files. Fixes #88529 --- libcxx/include/CMakeLists.txt | 16 +- libcxx/include/libcxx.imp | 855 -------------------------- libcxx/utils/CMakeLists.txt | 9 +- libcxx/utils/generate_iwyu_mapping.py | 30 +- 4 files changed, 37 insertions(+), 873 deletions(-) delete mode 100644 libcxx/include/libcxx.imp diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 4ecd834c5382..8269436a53e9 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -957,7 +957,6 @@ set(files istream iterator latch - libcxx.imp limits list locale @@ -1036,6 +1035,15 @@ foreach(f ${files}) list(APPEND _all_includes "${dst}") endforeach() +# Generate the IWYU mapping. This depends on all header files but it's also considered as an +# "include" for dependency tracking. +add_custom_command(OUTPUT "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_iwyu_mapping.py" "-o" "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + DEPENDS ${_all_includes} + COMMENT "Generate the mapping file for include-what-you-use" +) +list(APPEND _all_includes "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp") + add_custom_target(generate-cxx-headers ALL DEPENDS ${_all_includes}) add_library(cxx-headers INTERFACE) @@ -1074,6 +1082,12 @@ if (LIBCXX_INSTALL_HEADERS) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT cxx-headers) + # Install the generated IWYU file to the generic include dir. + install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + COMPONENT cxx-headers) + if (NOT CMAKE_CONFIGURATION_TYPES) add_custom_target(install-cxx-headers DEPENDS cxx-headers diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp deleted file mode 100644 index 1d12b6e8d86b..000000000000 --- a/libcxx/include/libcxx.imp +++ /dev/null @@ -1,855 +0,0 @@ -[ - { include: [ "<__algorithm/adjacent_find.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/all_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/any_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/binary_search.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/clamp.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/comp.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/comp_ref_type.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/copy_backward.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/copy_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/copy_move_common.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/copy_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/count.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/count_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/equal.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/equal_range.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/fill.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/fill_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/find.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/find_end.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/find_first_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/find_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/find_if_not.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/find_segment_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/fold.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/for_each.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/for_each_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/for_each_segment.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/generate.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/generate_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/half_positive.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/in_found_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/in_fun_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/in_in_out_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/in_in_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/in_out_out_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/in_out_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/includes.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/inplace_merge.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/is_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/is_heap_until.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/is_partitioned.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/is_permutation.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/is_sorted.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/is_sorted_until.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/iter_swap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/iterator_operations.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/lexicographical_compare.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/lexicographical_compare_three_way.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/lower_bound.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/make_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/make_projected.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/max.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/max_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/merge.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/min.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/min_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/min_max_result.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/minmax.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/minmax_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/mismatch.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/move.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/move_backward.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/next_permutation.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/none_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/nth_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/partial_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/partial_sort_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/partition.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/partition_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/partition_point.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pop_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/prev_permutation.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_any_all_none_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_count.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_equal.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_fill.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_find.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_for_each.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_frontend_dispatch.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_generate.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_is_partitioned.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_merge.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_move.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_replace.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_rotate_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_stable_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/pstl_transform.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/push_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_adjacent_find.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_all_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_any_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_binary_search.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_clamp.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_contains.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_contains_subrange.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_copy_backward.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_copy_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_copy_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_count.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_count_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_ends_with.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_equal.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_equal_range.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_fill.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_fill_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_find.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_find_end.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_find_first_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_find_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_find_if_not.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_for_each.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_for_each_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_generate.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_generate_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_includes.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_inplace_merge.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_is_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_is_heap_until.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_is_partitioned.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_is_permutation.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_is_sorted.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_is_sorted_until.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_iterator_concept.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_lexicographical_compare.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_lower_bound.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_make_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_max.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_max_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_merge.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_min.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_min_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_minmax.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_minmax_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_mismatch.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_move.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_move_backward.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_next_permutation.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_none_of.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_nth_element.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_partial_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_partial_sort_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_partition.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_partition_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_partition_point.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_pop_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_prev_permutation.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_push_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_remove.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_remove_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_remove_copy_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_remove_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_replace.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_replace_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_replace_copy_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_replace_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_reverse.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_reverse_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_rotate.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_rotate_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_sample.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_search.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_search_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_set_difference.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_set_intersection.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_set_symmetric_difference.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_set_union.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_shuffle.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_sort_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_stable_partition.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_stable_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_starts_with.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_swap_ranges.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_transform.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_unique.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_unique_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/ranges_upper_bound.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/remove.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/remove_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/remove_copy_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/remove_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/replace.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/replace_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/replace_copy_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/replace_if.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/reverse.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/reverse_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/rotate.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/rotate_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/sample.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/search.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/search_n.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/set_difference.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/set_intersection.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/set_symmetric_difference.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/set_union.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/shift_left.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/shift_right.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/shuffle.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/sift_down.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/simd_utils.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/sort_heap.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/stable_partition.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/stable_sort.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/swap_ranges.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/three_way_comp_ref_type.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/transform.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/uniform_random_bit_generator_adaptor.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/unique.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/unique_copy.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/unwrap_iter.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/unwrap_range.h>", "private", "", "public" ] }, - { include: [ "<__algorithm/upper_bound.h>", "private", "", "public" ] }, - { include: [ "<__atomic/aliases.h>", "private", "", "public" ] }, - { include: [ "<__atomic/atomic.h>", "private", "", "public" ] }, - { include: [ "<__atomic/atomic_base.h>", "private", "", "public" ] }, - { include: [ "<__atomic/atomic_flag.h>", "private", "", "public" ] }, - { include: [ "<__atomic/atomic_init.h>", "private", "", "public" ] }, - { include: [ "<__atomic/atomic_lock_free.h>", "private", "", "public" ] }, - { include: [ "<__atomic/atomic_sync.h>", "private", "", "public" ] }, - { include: [ "<__atomic/check_memory_order.h>", "private", "", "public" ] }, - { include: [ "<__atomic/contention_t.h>", "private", "", "public" ] }, - { include: [ "<__atomic/cxx_atomic_impl.h>", "private", "", "public" ] }, - { include: [ "<__atomic/fence.h>", "private", "", "public" ] }, - { include: [ "<__atomic/is_always_lock_free.h>", "private", "", "public" ] }, - { include: [ "<__atomic/kill_dependency.h>", "private", "", "public" ] }, - { include: [ "<__atomic/memory_order.h>", "private", "", "public" ] }, - { include: [ "<__bit/bit_cast.h>", "private", "", "public" ] }, - { include: [ "<__bit/bit_ceil.h>", "private", "", "public" ] }, - { include: [ "<__bit/bit_floor.h>", "private", "", "public" ] }, - { include: [ "<__bit/bit_log2.h>", "private", "", "public" ] }, - { include: [ "<__bit/bit_width.h>", "private", "", "public" ] }, - { include: [ "<__bit/blsr.h>", "private", "", "public" ] }, - { include: [ "<__bit/byteswap.h>", "private", "", "public" ] }, - { include: [ "<__bit/countl.h>", "private", "", "public" ] }, - { include: [ "<__bit/countr.h>", "private", "", "public" ] }, - { include: [ "<__bit/endian.h>", "private", "", "public" ] }, - { include: [ "<__bit/has_single_bit.h>", "private", "", "public" ] }, - { include: [ "<__bit/invert_if.h>", "private", "", "public" ] }, - { include: [ "<__bit/popcount.h>", "private", "", "public" ] }, - { include: [ "<__bit/rotate.h>", "private", "", "public" ] }, - { include: [ "<__charconv/chars_format.h>", "private", "", "public" ] }, - { include: [ "<__charconv/from_chars_integral.h>", "private", "", "public" ] }, - { include: [ "<__charconv/from_chars_result.h>", "private", "", "public" ] }, - { include: [ "<__charconv/tables.h>", "private", "", "public" ] }, - { include: [ "<__charconv/to_chars.h>", "private", "", "public" ] }, - { include: [ "<__charconv/to_chars_base_10.h>", "private", "", "public" ] }, - { include: [ "<__charconv/to_chars_floating_point.h>", "private", "", "public" ] }, - { include: [ "<__charconv/to_chars_integral.h>", "private", "", "public" ] }, - { include: [ "<__charconv/to_chars_result.h>", "private", "", "public" ] }, - { include: [ "<__charconv/traits.h>", "private", "", "public" ] }, - { include: [ "<__chrono/calendar.h>", "private", "", "public" ] }, - { include: [ "<__chrono/concepts.h>", "private", "", "public" ] }, - { include: [ "<__chrono/convert_to_timespec.h>", "private", "", "public" ] }, - { include: [ "<__chrono/convert_to_tm.h>", "private", "", "public" ] }, - { include: [ "<__chrono/day.h>", "private", "", "public" ] }, - { include: [ "<__chrono/duration.h>", "private", "", "public" ] }, - { include: [ "<__chrono/file_clock.h>", "private", "", "public" ] }, - { include: [ "<__chrono/formatter.h>", "private", "", "public" ] }, - { include: [ "<__chrono/hh_mm_ss.h>", "private", "", "public" ] }, - { include: [ "<__chrono/high_resolution_clock.h>", "private", "", "public" ] }, - { include: [ "<__chrono/leap_second.h>", "private", "", "public" ] }, - { include: [ "<__chrono/literals.h>", "private", "", "public" ] }, - { include: [ "<__chrono/local_info.h>", "private", "", "public" ] }, - { include: [ "<__chrono/month.h>", "private", "", "public" ] }, - { include: [ "<__chrono/month_weekday.h>", "private", "", "public" ] }, - { include: [ "<__chrono/monthday.h>", "private", "", "public" ] }, - { include: [ "<__chrono/ostream.h>", "private", "", "public" ] }, - { include: [ "<__chrono/parser_std_format_spec.h>", "private", "", "public" ] }, - { include: [ "<__chrono/statically_widen.h>", "private", "", "public" ] }, - { include: [ "<__chrono/steady_clock.h>", "private", "", "public" ] }, - { include: [ "<__chrono/sys_info.h>", "private", "", "public" ] }, - { include: [ "<__chrono/system_clock.h>", "private", "", "public" ] }, - { include: [ "<__chrono/time_point.h>", "private", "", "public" ] }, - { include: [ "<__chrono/time_zone.h>", "private", "", "public" ] }, - { include: [ "<__chrono/time_zone_link.h>", "private", "", "public" ] }, - { include: [ "<__chrono/tzdb.h>", "private", "", "public" ] }, - { include: [ "<__chrono/tzdb_list.h>", "private", "", "public" ] }, - { include: [ "<__chrono/weekday.h>", "private", "", "public" ] }, - { include: [ "<__chrono/year.h>", "private", "", "public" ] }, - { include: [ "<__chrono/year_month.h>", "private", "", "public" ] }, - { include: [ "<__chrono/year_month_day.h>", "private", "", "public" ] }, - { include: [ "<__chrono/year_month_weekday.h>", "private", "", "public" ] }, - { include: [ "<__compare/common_comparison_category.h>", "private", "", "public" ] }, - { include: [ "<__compare/compare_partial_order_fallback.h>", "private", "", "public" ] }, - { include: [ "<__compare/compare_strong_order_fallback.h>", "private", "", "public" ] }, - { include: [ "<__compare/compare_three_way.h>", "private", "", "public" ] }, - { include: [ "<__compare/compare_three_way_result.h>", "private", "", "public" ] }, - { include: [ "<__compare/compare_weak_order_fallback.h>", "private", "", "public" ] }, - { include: [ "<__compare/is_eq.h>", "private", "", "public" ] }, - { include: [ "<__compare/ordering.h>", "private", "", "public" ] }, - { include: [ "<__compare/partial_order.h>", "private", "", "public" ] }, - { include: [ "<__compare/strong_order.h>", "private", "", "public" ] }, - { include: [ "<__compare/synth_three_way.h>", "private", "", "public" ] }, - { include: [ "<__compare/three_way_comparable.h>", "private", "", "public" ] }, - { include: [ "<__compare/weak_order.h>", "private", "", "public" ] }, - { include: [ "<__concepts/arithmetic.h>", "private", "", "public" ] }, - { include: [ "<__concepts/assignable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/boolean_testable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/class_or_enum.h>", "private", "", "public" ] }, - { include: [ "<__concepts/common_reference_with.h>", "private", "", "public" ] }, - { include: [ "<__concepts/common_with.h>", "private", "", "public" ] }, - { include: [ "<__concepts/constructible.h>", "private", "", "public" ] }, - { include: [ "<__concepts/convertible_to.h>", "private", "", "public" ] }, - { include: [ "<__concepts/copyable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/derived_from.h>", "private", "", "public" ] }, - { include: [ "<__concepts/destructible.h>", "private", "", "public" ] }, - { include: [ "<__concepts/different_from.h>", "private", "", "public" ] }, - { include: [ "<__concepts/equality_comparable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/invocable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/movable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/predicate.h>", "private", "", "public" ] }, - { include: [ "<__concepts/regular.h>", "private", "", "public" ] }, - { include: [ "<__concepts/relation.h>", "private", "", "public" ] }, - { include: [ "<__concepts/same_as.h>", "private", "", "public" ] }, - { include: [ "<__concepts/semiregular.h>", "private", "", "public" ] }, - { include: [ "<__concepts/swappable.h>", "private", "", "public" ] }, - { include: [ "<__concepts/totally_ordered.h>", "private", "", "public" ] }, - { include: [ "<__condition_variable/condition_variable.h>", "private", "", "public" ] }, - { include: [ "<__coroutine/coroutine_handle.h>", "private", "", "public" ] }, - { include: [ "<__coroutine/coroutine_traits.h>", "private", "", "public" ] }, - { include: [ "<__coroutine/noop_coroutine_handle.h>", "private", "", "public" ] }, - { include: [ "<__coroutine/trivial_awaitables.h>", "private", "", "public" ] }, - { include: [ "<__exception/exception.h>", "private", "", "public" ] }, - { include: [ "<__exception/exception_ptr.h>", "private", "", "public" ] }, - { include: [ "<__exception/nested_exception.h>", "private", "", "public" ] }, - { include: [ "<__exception/operations.h>", "private", "", "public" ] }, - { include: [ "<__exception/terminate.h>", "private", "", "public" ] }, - { include: [ "<__expected/bad_expected_access.h>", "private", "", "public" ] }, - { include: [ "<__expected/expected.h>", "private", "", "public" ] }, - { include: [ "<__expected/unexpect.h>", "private", "", "public" ] }, - { include: [ "<__expected/unexpected.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/copy_options.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/directory_entry.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/directory_iterator.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/directory_options.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/file_status.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/file_time_type.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/file_type.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/filesystem_error.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/operations.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/path.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/path_iterator.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/perm_options.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/perms.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/recursive_directory_iterator.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/space_info.h>", "private", "", "public" ] }, - { include: [ "<__filesystem/u8path.h>", "private", "", "public" ] }, - { include: [ "<__format/buffer.h>", "private", "", "public" ] }, - { include: [ "<__format/concepts.h>", "private", "", "public" ] }, - { include: [ "<__format/container_adaptor.h>", "private", "", "public" ] }, - { include: [ "<__format/enable_insertable.h>", "private", "", "public" ] }, - { include: [ "<__format/escaped_output_table.h>", "private", "", "public" ] }, - { include: [ "<__format/extended_grapheme_cluster_table.h>", "private", "", "public" ] }, - { include: [ "<__format/format_arg.h>", "private", "", "public" ] }, - { include: [ "<__format/format_arg_store.h>", "private", "", "public" ] }, - { include: [ "<__format/format_args.h>", "private", "", "public" ] }, - { include: [ "<__format/format_context.h>", "private", "", "public" ] }, - { include: [ "<__format/format_error.h>", "private", "", "public" ] }, - { include: [ "<__format/format_functions.h>", "private", "", "public" ] }, - { include: [ "<__format/format_parse_context.h>", "private", "", "public" ] }, - { include: [ "<__format/format_string.h>", "private", "", "public" ] }, - { include: [ "<__format/format_to_n_result.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_bool.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_char.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_floating_point.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_integer.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_integral.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_output.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_pointer.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_string.h>", "private", "", "public" ] }, - { include: [ "<__format/formatter_tuple.h>", "private", "", "public" ] }, - { include: [ "<__format/indic_conjunct_break_table.h>", "private", "", "public" ] }, - { include: [ "<__format/parser_std_format_spec.h>", "private", "", "public" ] }, - { include: [ "<__format/range_default_formatter.h>", "private", "", "public" ] }, - { include: [ "<__format/range_formatter.h>", "private", "", "public" ] }, - { include: [ "<__format/unicode.h>", "private", "", "public" ] }, - { include: [ "<__format/width_estimation_table.h>", "private", "", "public" ] }, - { include: [ "<__format/write_escaped.h>", "private", "", "public" ] }, - { include: [ "<__functional/binary_function.h>", "private", "", "public" ] }, - { include: [ "<__functional/binary_negate.h>", "private", "", "public" ] }, - { include: [ "<__functional/bind.h>", "private", "", "public" ] }, - { include: [ "<__functional/bind_back.h>", "private", "", "public" ] }, - { include: [ "<__functional/bind_front.h>", "private", "", "public" ] }, - { include: [ "<__functional/binder1st.h>", "private", "", "public" ] }, - { include: [ "<__functional/binder2nd.h>", "private", "", "public" ] }, - { include: [ "<__functional/boyer_moore_searcher.h>", "private", "", "public" ] }, - { include: [ "<__functional/compose.h>", "private", "", "public" ] }, - { include: [ "<__functional/default_searcher.h>", "private", "", "public" ] }, - { include: [ "<__functional/function.h>", "private", "", "public" ] }, - { include: [ "<__functional/hash.h>", "private", "", "public" ] }, - { include: [ "<__functional/identity.h>", "private", "", "public" ] }, - { include: [ "<__functional/invoke.h>", "private", "", "public" ] }, - { include: [ "<__functional/is_transparent.h>", "private", "", "public" ] }, - { include: [ "<__functional/mem_fn.h>", "private", "", "public" ] }, - { include: [ "<__functional/mem_fun_ref.h>", "private", "", "public" ] }, - { include: [ "<__functional/not_fn.h>", "private", "", "public" ] }, - { include: [ "<__functional/operations.h>", "private", "", "public" ] }, - { include: [ "<__functional/perfect_forward.h>", "private", "", "public" ] }, - { include: [ "<__functional/pointer_to_binary_function.h>", "private", "", "public" ] }, - { include: [ "<__functional/pointer_to_unary_function.h>", "private", "", "public" ] }, - { include: [ "<__functional/ranges_operations.h>", "private", "", "public" ] }, - { include: [ "<__functional/reference_wrapper.h>", "private", "", "public" ] }, - { include: [ "<__functional/unary_function.h>", "private", "", "public" ] }, - { include: [ "<__functional/unary_negate.h>", "private", "", "public" ] }, - { include: [ "<__functional/weak_result_type.h>", "private", "", "public" ] }, - { include: [ "<__fwd/array.h>", "private", "", "public" ] }, - { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, - { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, - { include: [ "<__fwd/complex.h>", "private", "", "public" ] }, - { include: [ "<__fwd/deque.h>", "private", "", "public" ] }, - { include: [ "<__fwd/format.h>", "private", "", "public" ] }, - { include: [ "<__fwd/fstream.h>", "private", "", "public" ] }, - { include: [ "<__fwd/functional.h>", "private", "", "public" ] }, - { include: [ "<__fwd/ios.h>", "private", "", "public" ] }, - { include: [ "<__fwd/istream.h>", "private", "", "public" ] }, - { include: [ "<__fwd/mdspan.h>", "private", "", "public" ] }, - { include: [ "<__fwd/memory.h>", "private", "", "public" ] }, - { include: [ "<__fwd/memory_resource.h>", "private", "", "public" ] }, - { include: [ "<__fwd/ostream.h>", "private", "", "public" ] }, - { include: [ "<__fwd/pair.h>", "private", "", "public" ] }, - { include: [ "<__fwd/queue.h>", "private", "", "public" ] }, - { include: [ "<__fwd/span.h>", "private", "", "public" ] }, - { include: [ "<__fwd/sstream.h>", "private", "", "public" ] }, - { include: [ "<__fwd/stack.h>", "private", "", "public" ] }, - { include: [ "<__fwd/streambuf.h>", "private", "", "public" ] }, - { include: [ "<__fwd/string.h>", "private", "", "public" ] }, - { include: [ "<__fwd/string_view.h>", "private", "", "public" ] }, - { include: [ "<__fwd/subrange.h>", "private", "", "public" ] }, - { include: [ "<__fwd/tuple.h>", "private", "", "public" ] }, - { include: [ "<__fwd/vector.h>", "private", "", "public" ] }, - { include: [ "<__ios/fpos.h>", "private", "", "public" ] }, - { include: [ "<__iterator/access.h>", "private", "", "public" ] }, - { include: [ "<__iterator/advance.h>", "private", "", "public" ] }, - { include: [ "<__iterator/back_insert_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/bounded_iter.h>", "private", "", "public" ] }, - { include: [ "<__iterator/common_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/concepts.h>", "private", "", "public" ] }, - { include: [ "<__iterator/counted_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/cpp17_iterator_concepts.h>", "private", "", "public" ] }, - { include: [ "<__iterator/data.h>", "private", "", "public" ] }, - { include: [ "<__iterator/default_sentinel.h>", "private", "", "public" ] }, - { include: [ "<__iterator/distance.h>", "private", "", "public" ] }, - { include: [ "<__iterator/empty.h>", "private", "", "public" ] }, - { include: [ "<__iterator/erase_if_container.h>", "private", "", "public" ] }, - { include: [ "<__iterator/front_insert_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/incrementable_traits.h>", "private", "", "public" ] }, - { include: [ "<__iterator/indirectly_comparable.h>", "private", "", "public" ] }, - { include: [ "<__iterator/insert_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/istream_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/istreambuf_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/iter_move.h>", "private", "", "public" ] }, - { include: [ "<__iterator/iter_swap.h>", "private", "", "public" ] }, - { include: [ "<__iterator/iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/iterator_traits.h>", "private", "", "public" ] }, - { include: [ "<__iterator/iterator_with_data.h>", "private", "", "public" ] }, - { include: [ "<__iterator/mergeable.h>", "private", "", "public" ] }, - { include: [ "<__iterator/move_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/move_sentinel.h>", "private", "", "public" ] }, - { include: [ "<__iterator/next.h>", "private", "", "public" ] }, - { include: [ "<__iterator/ostream_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/ostreambuf_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/permutable.h>", "private", "", "public" ] }, - { include: [ "<__iterator/prev.h>", "private", "", "public" ] }, - { include: [ "<__iterator/projected.h>", "private", "", "public" ] }, - { include: [ "<__iterator/ranges_iterator_traits.h>", "private", "", "public" ] }, - { include: [ "<__iterator/readable_traits.h>", "private", "", "public" ] }, - { include: [ "<__iterator/reverse_access.h>", "private", "", "public" ] }, - { include: [ "<__iterator/reverse_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/segmented_iterator.h>", "private", "", "public" ] }, - { include: [ "<__iterator/size.h>", "private", "", "public" ] }, - { include: [ "<__iterator/sortable.h>", "private", "", "public" ] }, - { include: [ "<__iterator/unreachable_sentinel.h>", "private", "", "public" ] }, - { include: [ "<__iterator/wrap_iter.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/android.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/bsd_locale_defaults.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/bsd_locale_fallbacks.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/fuchsia.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/ibm.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/locale_guard.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/musl.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/newlib.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/openbsd.h>", "private", "", "public" ] }, - { include: [ "<__locale_dir/locale_base_api/win32.h>", "private", "", "public" ] }, - { include: [ "<__math/abs.h>", "private", "", "public" ] }, - { include: [ "<__math/copysign.h>", "private", "", "public" ] }, - { include: [ "<__math/error_functions.h>", "private", "", "public" ] }, - { include: [ "<__math/exponential_functions.h>", "private", "", "public" ] }, - { include: [ "<__math/fdim.h>", "private", "", "public" ] }, - { include: [ "<__math/fma.h>", "private", "", "public" ] }, - { include: [ "<__math/gamma.h>", "private", "", "public" ] }, - { include: [ "<__math/hyperbolic_functions.h>", "private", "", "public" ] }, - { include: [ "<__math/hypot.h>", "private", "", "public" ] }, - { include: [ "<__math/inverse_hyperbolic_functions.h>", "private", "", "public" ] }, - { include: [ "<__math/inverse_trigonometric_functions.h>", "private", "", "public" ] }, - { include: [ "<__math/logarithms.h>", "private", "", "public" ] }, - { include: [ "<__math/min_max.h>", "private", "", "public" ] }, - { include: [ "<__math/modulo.h>", "private", "", "public" ] }, - { include: [ "<__math/remainder.h>", "private", "", "public" ] }, - { include: [ "<__math/roots.h>", "private", "", "public" ] }, - { include: [ "<__math/rounding_functions.h>", "private", "", "public" ] }, - { include: [ "<__math/traits.h>", "private", "", "public" ] }, - { include: [ "<__math/trigonometric_functions.h>", "private", "", "public" ] }, - { include: [ "<__mdspan/default_accessor.h>", "private", "", "public" ] }, - { include: [ "<__mdspan/extents.h>", "private", "", "public" ] }, - { include: [ "<__mdspan/layout_left.h>", "private", "", "public" ] }, - { include: [ "<__mdspan/layout_right.h>", "private", "", "public" ] }, - { include: [ "<__mdspan/layout_stride.h>", "private", "", "public" ] }, - { include: [ "<__mdspan/mdspan.h>", "private", "", "public" ] }, - { include: [ "<__memory/addressof.h>", "private", "", "public" ] }, - { include: [ "<__memory/align.h>", "private", "", "public" ] }, - { include: [ "<__memory/aligned_alloc.h>", "private", "", "public" ] }, - { include: [ "<__memory/allocate_at_least.h>", "private", "", "public" ] }, - { include: [ "<__memory/allocation_guard.h>", "private", "", "public" ] }, - { include: [ "<__memory/allocator.h>", "private", "", "public" ] }, - { include: [ "<__memory/allocator_arg_t.h>", "private", "", "public" ] }, - { include: [ "<__memory/allocator_destructor.h>", "private", "", "public" ] }, - { include: [ "<__memory/allocator_traits.h>", "private", "", "public" ] }, - { include: [ "<__memory/assume_aligned.h>", "private", "", "public" ] }, - { include: [ "<__memory/auto_ptr.h>", "private", "", "public" ] }, - { include: [ "<__memory/builtin_new_allocator.h>", "private", "", "public" ] }, - { include: [ "<__memory/compressed_pair.h>", "private", "", "public" ] }, - { include: [ "<__memory/concepts.h>", "private", "", "public" ] }, - { include: [ "<__memory/construct_at.h>", "private", "", "public" ] }, - { include: [ "<__memory/destruct_n.h>", "private", "", "public" ] }, - { include: [ "<__memory/pointer_traits.h>", "private", "", "public" ] }, - { include: [ "<__memory/ranges_construct_at.h>", "private", "", "public" ] }, - { include: [ "<__memory/ranges_uninitialized_algorithms.h>", "private", "", "public" ] }, - { include: [ "<__memory/raw_storage_iterator.h>", "private", "", "public" ] }, - { include: [ "<__memory/shared_ptr.h>", "private", "", "public" ] }, - { include: [ "<__memory/swap_allocator.h>", "private", "", "public" ] }, - { include: [ "<__memory/temp_value.h>", "private", "", "public" ] }, - { include: [ "<__memory/temporary_buffer.h>", "private", "", "public" ] }, - { include: [ "<__memory/uninitialized_algorithms.h>", "private", "", "public" ] }, - { include: [ "<__memory/unique_ptr.h>", "private", "", "public" ] }, - { include: [ "<__memory/uses_allocator.h>", "private", "", "public" ] }, - { include: [ "<__memory/uses_allocator_construction.h>", "private", "", "public" ] }, - { include: [ "<__memory/voidify.h>", "private", "", "public" ] }, - { include: [ "<__memory_resource/memory_resource.h>", "private", "", "public" ] }, - { include: [ "<__memory_resource/monotonic_buffer_resource.h>", "private", "", "public" ] }, - { include: [ "<__memory_resource/polymorphic_allocator.h>", "private", "", "public" ] }, - { include: [ "<__memory_resource/pool_options.h>", "private", "", "public" ] }, - { include: [ "<__memory_resource/synchronized_pool_resource.h>", "private", "", "public" ] }, - { include: [ "<__memory_resource/unsynchronized_pool_resource.h>", "private", "", "public" ] }, - { include: [ "<__mutex/lock_guard.h>", "private", "", "public" ] }, - { include: [ "<__mutex/mutex.h>", "private", "", "public" ] }, - { include: [ "<__mutex/once_flag.h>", "private", "", "public" ] }, - { include: [ "<__mutex/tag_types.h>", "private", "", "public" ] }, - { include: [ "<__mutex/unique_lock.h>", "private", "", "public" ] }, - { include: [ "<__numeric/accumulate.h>", "private", "", "public" ] }, - { include: [ "<__numeric/adjacent_difference.h>", "private", "", "public" ] }, - { include: [ "<__numeric/exclusive_scan.h>", "private", "", "public" ] }, - { include: [ "<__numeric/gcd_lcm.h>", "private", "", "public" ] }, - { include: [ "<__numeric/inclusive_scan.h>", "private", "", "public" ] }, - { include: [ "<__numeric/inner_product.h>", "private", "", "public" ] }, - { include: [ "<__numeric/iota.h>", "private", "", "public" ] }, - { include: [ "<__numeric/midpoint.h>", "private", "", "public" ] }, - { include: [ "<__numeric/partial_sum.h>", "private", "", "public" ] }, - { include: [ "<__numeric/pstl_reduce.h>", "private", "", "public" ] }, - { include: [ "<__numeric/pstl_transform_reduce.h>", "private", "", "public" ] }, - { include: [ "<__numeric/reduce.h>", "private", "", "public" ] }, - { include: [ "<__numeric/saturation_arithmetic.h>", "private", "", "public" ] }, - { include: [ "<__numeric/transform_exclusive_scan.h>", "private", "", "public" ] }, - { include: [ "<__numeric/transform_inclusive_scan.h>", "private", "", "public" ] }, - { include: [ "<__numeric/transform_reduce.h>", "private", "", "public" ] }, - { include: [ "<__random/bernoulli_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/binomial_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/cauchy_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/chi_squared_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/clamp_to_integral.h>", "private", "", "public" ] }, - { include: [ "<__random/default_random_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/discard_block_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/discrete_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/exponential_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/extreme_value_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/fisher_f_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/gamma_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/generate_canonical.h>", "private", "", "public" ] }, - { include: [ "<__random/geometric_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/independent_bits_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/is_seed_sequence.h>", "private", "", "public" ] }, - { include: [ "<__random/is_valid.h>", "private", "", "public" ] }, - { include: [ "<__random/knuth_b.h>", "private", "", "public" ] }, - { include: [ "<__random/linear_congruential_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/log2.h>", "private", "", "public" ] }, - { include: [ "<__random/lognormal_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/mersenne_twister_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/negative_binomial_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/normal_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/piecewise_constant_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/piecewise_linear_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/poisson_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/random_device.h>", "private", "", "public" ] }, - { include: [ "<__random/ranlux.h>", "private", "", "public" ] }, - { include: [ "<__random/seed_seq.h>", "private", "", "public" ] }, - { include: [ "<__random/shuffle_order_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/student_t_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/subtract_with_carry_engine.h>", "private", "", "public" ] }, - { include: [ "<__random/uniform_int_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/uniform_random_bit_generator.h>", "private", "", "public" ] }, - { include: [ "<__random/uniform_real_distribution.h>", "private", "", "public" ] }, - { include: [ "<__random/weibull_distribution.h>", "private", "", "public" ] }, - { include: [ "<__ranges/access.h>", "private", "", "public" ] }, - { include: [ "<__ranges/all.h>", "private", "", "public" ] }, - { include: [ "<__ranges/as_rvalue_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/chunk_by_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/common_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/concepts.h>", "private", "", "public" ] }, - { include: [ "<__ranges/container_compatible_range.h>", "private", "", "public" ] }, - { include: [ "<__ranges/counted.h>", "private", "", "public" ] }, - { include: [ "<__ranges/dangling.h>", "private", "", "public" ] }, - { include: [ "<__ranges/data.h>", "private", "", "public" ] }, - { include: [ "<__ranges/drop_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/drop_while_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/elements_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/empty.h>", "private", "", "public" ] }, - { include: [ "<__ranges/empty_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/enable_borrowed_range.h>", "private", "", "public" ] }, - { include: [ "<__ranges/enable_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/filter_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/from_range.h>", "private", "", "public" ] }, - { include: [ "<__ranges/iota_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/istream_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/join_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/lazy_split_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/movable_box.h>", "private", "", "public" ] }, - { include: [ "<__ranges/non_propagating_cache.h>", "private", "", "public" ] }, - { include: [ "<__ranges/owning_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/range_adaptor.h>", "private", "", "public" ] }, - { include: [ "<__ranges/rbegin.h>", "private", "", "public" ] }, - { include: [ "<__ranges/ref_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/rend.h>", "private", "", "public" ] }, - { include: [ "<__ranges/repeat_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/reverse_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/single_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/size.h>", "private", "", "public" ] }, - { include: [ "<__ranges/split_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/subrange.h>", "private", "", "public" ] }, - { include: [ "<__ranges/take_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/take_while_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/to.h>", "private", "", "public" ] }, - { include: [ "<__ranges/transform_view.h>", "private", "", "public" ] }, - { include: [ "<__ranges/view_interface.h>", "private", "", "public" ] }, - { include: [ "<__ranges/views.h>", "private", "", "public" ] }, - { include: [ "<__ranges/zip_view.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/atomic_unique_lock.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/intrusive_list_view.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/intrusive_shared_ptr.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/stop_callback.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/stop_source.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/stop_state.h>", "private", "", "public" ] }, - { include: [ "<__stop_token/stop_token.h>", "private", "", "public" ] }, - { include: [ "<__string/char_traits.h>", "private", "", "public" ] }, - { include: [ "<__string/constexpr_c_functions.h>", "private", "", "public" ] }, - { include: [ "<__string/extern_template_lists.h>", "private", "", "public" ] }, - { include: [ "<__system_error/errc.h>", "private", "", "public" ] }, - { include: [ "<__system_error/error_category.h>", "private", "", "public" ] }, - { include: [ "<__system_error/error_code.h>", "private", "", "public" ] }, - { include: [ "<__system_error/error_condition.h>", "private", "", "public" ] }, - { include: [ "<__system_error/system_error.h>", "private", "", "public" ] }, - { include: [ "<__thread/formatter.h>", "private", "", "public" ] }, - { include: [ "<__thread/id.h>", "private", "", "public" ] }, - { include: [ "<__thread/jthread.h>", "private", "", "public" ] }, - { include: [ "<__thread/poll_with_backoff.h>", "private", "", "public" ] }, - { include: [ "<__thread/support.h>", "private", "", "public" ] }, - { include: [ "<__thread/support.h>", "private", "", "public" ] }, - { include: [ "<__thread/support.h>", "private", "", "public" ] }, - { include: [ "<__thread/support.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, - { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, - { include: [ "<__thread/this_thread.h>", "private", "", "public" ] }, - { include: [ "<__thread/thread.h>", "private", "", "public" ] }, - { include: [ "<__thread/timed_backoff_policy.h>", "private", "", "public" ] }, - { include: [ "<__tuple/find_index.h>", "private", "", "public" ] }, - { include: [ "<__tuple/make_tuple_types.h>", "private", "", "public" ] }, - { include: [ "<__tuple/sfinae_helpers.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_element.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_indices.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_like.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_like_ext.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_like_no_subrange.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_size.h>", "private", "", "public" ] }, - { include: [ "<__tuple/tuple_types.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/add_const.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/add_cv.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/add_lvalue_reference.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/add_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/add_rvalue_reference.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/add_volatile.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/aligned_storage.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/aligned_union.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/alignment_of.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/apply_cv.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/can_extract_key.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/common_reference.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/common_type.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/conditional.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/conjunction.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/copy_cv.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/copy_cvref.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/datasizeof.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/decay.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/dependent_type.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/desugars_to.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/disjunction.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/enable_if.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/extent.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/has_unique_object_representation.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/has_virtual_destructor.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/integral_constant.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/invoke.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_abstract.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_aggregate.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_allocator.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_always_bitcastable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_arithmetic.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_array.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_assignable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_base_of.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_bounded_array.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_callable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_char_like_type.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_class.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_compound.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_const.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_constant_evaluated.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_constructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_convertible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_core_convertible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_destructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_empty.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_enum.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_equality_comparable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_execution_policy.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_final.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_floating_point.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_function.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_fundamental.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_implicitly_default_constructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_integral.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_literal_type.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_member_function_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_member_object_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_member_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_nothrow_assignable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_nothrow_constructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_nothrow_convertible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_nothrow_destructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_null_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_object.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_pod.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_polymorphic.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_primary_template.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_reference.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_reference_wrapper.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_referenceable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_same.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_scalar.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_scoped_enum.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_signed.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_signed_integer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_specialization.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_standard_layout.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_swappable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivial.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivially_assignable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivially_constructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivially_copyable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivially_destructible.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivially_lexicographically_comparable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_trivially_relocatable.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_unbounded_array.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_union.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_unsigned.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_unsigned_integer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_valid_expansion.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_void.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/is_volatile.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/lazy.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/make_32_64_or_128_bit.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/make_const_lvalue_ref.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/make_signed.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/make_unsigned.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/maybe_const.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/nat.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/negation.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/noexcept_move_assign_container.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/promote.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/rank.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_all_extents.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_const.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_const_ref.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_cv.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_cvref.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_extent.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_pointer.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_reference.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/remove_volatile.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/result_of.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/strip_signature.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/type_identity.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/type_list.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/underlying_type.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/unwrap_ref.h>", "private", "", "public" ] }, - { include: [ "<__type_traits/void_t.h>", "private", "", "public" ] }, - { include: [ "<__utility/as_const.h>", "private", "", "public" ] }, - { include: [ "<__utility/as_lvalue.h>", "private", "", "public" ] }, - { include: [ "<__utility/auto_cast.h>", "private", "", "public" ] }, - { include: [ "<__utility/cmp.h>", "private", "", "public" ] }, - { include: [ "<__utility/convert_to_integral.h>", "private", "", "public" ] }, - { include: [ "<__utility/declval.h>", "private", "", "public" ] }, - { include: [ "<__utility/empty.h>", "private", "", "public" ] }, - { include: [ "<__utility/exception_guard.h>", "private", "", "public" ] }, - { include: [ "<__utility/exchange.h>", "private", "", "public" ] }, - { include: [ "<__utility/forward.h>", "private", "", "public" ] }, - { include: [ "<__utility/forward_like.h>", "private", "", "public" ] }, - { include: [ "<__utility/in_place.h>", "private", "", "public" ] }, - { include: [ "<__utility/integer_sequence.h>", "private", "", "public" ] }, - { include: [ "<__utility/is_pointer_in_range.h>", "private", "", "public" ] }, - { include: [ "<__utility/is_valid_range.h>", "private", "", "public" ] }, - { include: [ "<__utility/move.h>", "private", "", "public" ] }, - { include: [ "<__utility/no_destroy.h>", "private", "", "public" ] }, - { include: [ "<__utility/pair.h>", "private", "", "public" ] }, - { include: [ "<__utility/piecewise_construct.h>", "private", "", "public" ] }, - { include: [ "<__utility/priority_tag.h>", "private", "", "public" ] }, - { include: [ "<__utility/rel_ops.h>", "private", "", "public" ] }, - { include: [ "<__utility/small_buffer.h>", "private", "", "public" ] }, - { include: [ "<__utility/swap.h>", "private", "", "public" ] }, - { include: [ "<__utility/to_underlying.h>", "private", "", "public" ] }, - { include: [ "<__utility/unreachable.h>", "private", "", "public" ] }, - { include: [ "<__variant/monostate.h>", "private", "", "public" ] }, -] diff --git a/libcxx/utils/CMakeLists.txt b/libcxx/utils/CMakeLists.txt index 7a573535e1ef..1116531fa065 100644 --- a/libcxx/utils/CMakeLists.txt +++ b/libcxx/utils/CMakeLists.txt @@ -55,12 +55,6 @@ add_custom_target(libcxx-indic-conjunct-break-table "${LIBCXX_SOURCE_DIR}/include/__format/indic_conjunct_break_table.h" COMMENT "Generate the Indic Conjunct Break header") -add_custom_target(libcxx-generate-iwyu-mapping - COMMAND - "${Python3_EXECUTABLE}" - "${LIBCXX_SOURCE_DIR}/utils/generate_iwyu_mapping.py" - COMMENT "Generate the mapping file for include-what-you-use") - add_custom_target(libcxx-generate-files DEPENDS libcxx-generate-feature-test-macros libcxx-generate-std-clang-module-header @@ -70,6 +64,5 @@ add_custom_target(libcxx-generate-files libcxx-generate-extended-grapheme-cluster-tests libcxx-generate-escaped-output-table libcxx-generate-width-estimation-table - libcxx-indic-conjunct-break-table - libcxx-generate-iwyu-mapping + libcxx-indic-conjunct-break-table COMMENT "Create all the auto-generated files in libc++ and its tests.") diff --git a/libcxx/utils/generate_iwyu_mapping.py b/libcxx/utils/generate_iwyu_mapping.py index 33607f199684..b780fd54c6a4 100644 --- a/libcxx/utils/generate_iwyu_mapping.py +++ b/libcxx/utils/generate_iwyu_mapping.py @@ -1,9 +1,11 @@ #!/usr/bin/env python +import argparse import libcxx.header_information import os import pathlib import re +import sys import typing def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]: @@ -51,7 +53,18 @@ def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]: else: return None -def main(): + +def main(argv: typing.List[str]): + parser = argparse.ArgumentParser() + parser.add_argument( + "-o", + help="File to output the IWYU mappings into", + type=argparse.FileType("w"), + required=True, + dest="output", + ) + args = parser.parse_args(argv) + mappings = [] # Pairs of (header, public_header) for header in libcxx.header_information.all_headers: public_headers = IWYU_mapping(header) @@ -64,13 +77,12 @@ def main(): if public not in libcxx.header_information.public_headers: raise RuntimeError(f"{header}: Header {public} is not a valid header") - with open(libcxx.header_information.include / "libcxx.imp", "w") as f: - f.write("[\n") - for header, public in sorted(mappings): - f.write( - f' {{ include: [ "<{header}>", "private", "<{public}>", "public" ] }},\n' - ) - f.write("]\n") + args.output.write("[\n") + for header, public in sorted(mappings): + args.output.write( + f' {{ include: [ "<{header}>", "private", "<{public}>", "public" ] }},\n' + ) + args.output.write("]\n") if __name__ == "__main__": - main() + main(sys.argv[1:]) -- GitLab From c61f0a8e94004b05d9ec115d3bff8cff331b4491 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 22 Apr 2024 08:46:53 -0400 Subject: [PATCH 156/357] [libc++] Remove stray CMake install step for modulemap file (#89394) The modulemap file is not generated anymore, so it's just part of our list of includes and gets installed like every other header. We don't need a special step to install it anymore. This was overlooked when I removed the generation of the modulemap file. --- libcxx/include/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 8269436a53e9..1296c536bc88 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -1076,12 +1076,6 @@ if (LIBCXX_INSTALL_HEADERS) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT cxx-headers) - # Install the generated modulemap file to the generic include dir. - install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" - DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}" - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - COMPONENT cxx-headers) - # Install the generated IWYU file to the generic include dir. install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}" -- GitLab From e8b31fb39d9728e7505dfee7630158f14bc224de Mon Sep 17 00:00:00 2001 From: "Oleksandr \"Alex\" Zinenko" Date: Mon, 22 Apr 2024 14:49:28 +0200 Subject: [PATCH 157/357] [mlir] fix latex formulas in the tutorial --- mlir/docs/Tutorials/transform/ChH.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mlir/docs/Tutorials/transform/ChH.md b/mlir/docs/Tutorials/transform/ChH.md index f4dae5c1b99b..aadfddb89393 100644 --- a/mlir/docs/Tutorials/transform/ChH.md +++ b/mlir/docs/Tutorials/transform/ChH.md @@ -583,10 +583,11 @@ LLVM IR and processed by the LLVM compiler to produce an executable or JITted. The generated code runs in ~420ms on an Intel processor with Skylake microarchitecture clocked at 2.0GHz. Given that the computation performs -$5*80*100*128*(2*3*3*128 + 2) ~= 5.9 * 10^9$ floating point operations, it -reaches ~14 GFlops. With 1 FMA unit available, the single-core performance of -the test processor is 64 GFlops $16 * 2 * 2 * 10^9$, where 16 is the vector -width), so only 22% of the theoretical peak is achieved. +$`5 \cdot 80 \cdot 100 \cdot 128 \cdot (2 \cdot 3 \cdot 3 \cdot 128 + 2) \approx 5.9 * 10^9`$ +floating point operations, it reaches ~14 GFlops. With 1 FMA unit available, +the single-core performance of the test processor is 64 GFlops +($`16 \cdot 2 \cdot 2 \cdot 10^9`$, where 16 is the vector width), so only +22% of the theoretical peak is achieved. The code produced by Halide runs in ~120ms on the same processor, a 3.5x improvement and 77% of peak. Let us analyze the generated assembly to understand -- GitLab From 35b292efc6fc31b884255d7cb46db7d6346c6f46 Mon Sep 17 00:00:00 2001 From: Steven Varoumas Date: Mon, 22 Apr 2024 13:54:01 +0100 Subject: [PATCH 158/357] [mlir][Hoisting] Hoisting vector.extract/vector.broadcast pairs (#86108) This transformation, inspired by what is done in hoist_redundant_transfers, hoists pairs of extract/broadcast operations out of scf.for loops. It changes a loop of the form: ``` %res = scf.for _ = _ to _ step _ iter_args(%iarg = %v) -> (t1) { %e = vector.extract %iarg : t1 to t2 %u = "some_use"(%e) : (t2) -> t2 %b = vector.broadcast %u : t2 to t1 scf.yield %b : t1 } ``` into the following: ``` %e = vector.extract %v: t1 to t2 %res' = scf.for _ = _ to _ step _ iter_args(%iarg = %e) -> (t2) { %u' = "some_use"(%iarg) : (t2) -> t2 scf.yield %u' : t2 } %res = vector.broadcast %res' : t2 to t1 ``` --- .../Linalg/TransformOps/LinalgTransformOps.td | 36 +++++ .../mlir/Dialect/Linalg/Transforms/Hoisting.h | 11 ++ .../TransformOps/LinalgTransformOps.cpp | 15 +++ .../Dialect/Linalg/Transforms/Hoisting.cpp | 126 ++++++++++++++++++ mlir/test/Dialect/Linalg/hoisting.mlir | 109 +++++++++++++++ 5 files changed, 297 insertions(+) diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td index 8edaa7db6cef..157dc671f720 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td @@ -2206,6 +2206,42 @@ def HoistRedundantVectorTransfersOp : }]; } +//===----------------------------------------------------------------------===// +// HoistRedundantVectorBroadcastsOp +//===----------------------------------------------------------------------===// + +def HoistRedundantVectorBroadcastsOp : + Op { + let description = [{ + Hoist vector.extract / vector.broadcasts pairs out of immediately + enclosing scf::ForOp iteratively. + + #### Return modes: + + The operation always succeeds and returns a handle to the transformed + function op. + }]; + + let arguments = (ins TransformHandleTypeInterface:$target); + let results = (outs TransformHandleTypeInterface:$transformed); + + let assemblyFormat = "$target attr-dict `:` functional-type(operands, results) "; + + let builders = [ + OpBuilder<(ins "Value":$target)>, + ]; + let extraClassDeclaration = [{ + ::mlir::DiagnosedSilenceableFailure applyToOne( + ::mlir::transform::TransformRewriter &rewriter, + ::mlir::Operation *target, + ::mlir::transform::ApplyToEachResultList &results, + ::mlir::transform::TransformState &state); + }]; +} + //===----------------------------------------------------------------------===// // ConvertConv2DToImg2ColOp //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/Hoisting.h b/mlir/include/mlir/Dialect/Linalg/Transforms/Hoisting.h index 186e83a57580..236c2ce7d48e 100644 --- a/mlir/include/mlir/Dialect/Linalg/Transforms/Hoisting.h +++ b/mlir/include/mlir/Dialect/Linalg/Transforms/Hoisting.h @@ -43,6 +43,17 @@ namespace linalg { /// when used on distributed loops with memref semantics! void hoistRedundantVectorTransfers(Operation *root); +/// Hoist vector.extract/vector.broadcast pairs out of immediately enclosing +/// scf::ForOp iteratively, if the following conditions are met: +/// 1. The vector.extract operation is applied on an iter_argument, and no +/// other operator is using this argument in the body of the loop. +/// 2. The position of the vector.extract is either a static value, or defined +/// outside of the loop. +/// 3. The vector.broadcast operation is yielded by the loop. +/// To improve hoisting opportunities, call the `moveLoopInvariantCode` helper +/// function on the candidate loop above which to hoist. +void hoistRedundantVectorBroadcasts(RewriterBase &rewriter, Operation *root); + } // namespace linalg } // namespace mlir diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp index 3c3d968fbb86..82020c035271 100644 --- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp +++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp @@ -3306,6 +3306,21 @@ transform::HoistRedundantVectorTransfersOp::applyToOne( return DiagnosedSilenceableFailure::success(); } +//===----------------------------------------------------------------------===// +// HoistRedundantVectorBroadcastsOp +//===----------------------------------------------------------------------===// + +DiagnosedSilenceableFailure +transform::HoistRedundantVectorBroadcastsOp::applyToOne( + transform::TransformRewriter &rewriter, mlir::Operation *target, + transform::ApplyToEachResultList &results, + transform::TransformState &state) { + rewriter.setInsertionPoint(target); + linalg::hoistRedundantVectorBroadcasts(rewriter, target); + results.push_back(target); + return DiagnosedSilenceableFailure::success(); +} + //===----------------------------------------------------------------------===// // ConvertConv2DToImg2ColOp. //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/Linalg/Transforms/Hoisting.cpp b/mlir/lib/Dialect/Linalg/Transforms/Hoisting.cpp index 34c9b2c28296..94f6b6029875 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Hoisting.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Hoisting.cpp @@ -43,6 +43,132 @@ using llvm::dbgs; using namespace mlir; using namespace mlir::linalg; +/// Replace `loop` with a new loop that has a different init operand at +/// position `index`. The body of this loop is moved over to the new loop. +/// +/// `newInitOperands` specifies the replacement "init" operands. +/// `newYieldValue` is the replacement yield value of the loop at position +/// `index`. +static scf::ForOp replaceWithDifferentYield(RewriterBase &rewriter, + scf::ForOp loop, + Value newInitOperand, + unsigned index, + Value newYieldValue) { + OpBuilder::InsertionGuard g(rewriter); + rewriter.setInsertionPoint(loop.getOperation()); + auto inits = llvm::to_vector(loop.getInits()); + + // Replace the init value with the new operand. + assert(index < inits.size()); + inits[index] = newInitOperand; + + scf::ForOp newLoop = rewriter.create( + loop.getLoc(), loop.getLowerBound(), loop.getUpperBound(), loop.getStep(), + inits, [](OpBuilder &, Location, Value, ValueRange) {}); + + // Generate the new yield with the replaced operand. + auto yieldOp = cast(loop.getBody()->getTerminator()); + yieldOp.setOperand(index, newYieldValue); + + // Move the loop body to the new op. + rewriter.mergeBlocks(loop.getBody(), newLoop.getBody(), + newLoop.getBody()->getArguments()); + + // Replace the old loop. + rewriter.replaceOp(loop.getOperation(), newLoop->getResults()); + return newLoop; +} + +// Hoist out a pair of corresponding vector.extract+vector.broadcast +// operations. This function transforms a loop like this: +// %res = scf.for _ = _ to _ step _ iter_args(%iarg = %v) -> (t1) { +// %e = vector.extract %iarg : t1 to t2 +// %u = "some_use"(%e) : (t2) -> t2 +// %b = vector.broadcast %u : t2 to t1 +// scf.yield %b : t1 +// } +// into the following: +// %e = vector.extract %v: t1 to t2 +// %res' = scf.for _ = _ to _ step _ iter_args(%iarg = %e) -> (t2) { +// %u' = "some_use"(%iarg) : (t2) -> t2 +// scf.yield %u' : t2 +// } +// %res = vector.broadcast %res' : t2 to t1 +void mlir::linalg::hoistRedundantVectorBroadcasts(RewriterBase &rewriter, + Operation *root) { + bool changed = true; + while (changed) { + changed = false; + // First move loop invariant ops outside of their loop. This needs to be + // done before as we cannot move ops without interrupting the function walk. + root->walk( + [&](LoopLikeOpInterface loopLike) { moveLoopInvariantCode(loopLike); }); + + root->walk([&](vector::ExtractOp extractOp) { + LLVM_DEBUG(DBGS() << "Candidate for hoisting: " + << *extractOp.getOperation() << "\n"); + + auto loop = dyn_cast(extractOp->getParentOp()); + if (!loop) + return WalkResult::advance(); + + // Check that the vector to extract from is a BlockArgument. + auto blockArg = dyn_cast(extractOp.getVector()); + if (!blockArg) + return WalkResult::advance(); + + // Check that the blockArg is an iter_arg of the loop. + OpOperand *initArg = loop.getTiedLoopInit(blockArg); + if (!initArg) + return WalkResult::advance(); + + // If the iter_arg does not have only one use, it won't be possible to + // hoist the extractOp out. + if (!blockArg.hasOneUse()) + return WalkResult::advance(); + + unsigned index = blockArg.getArgNumber() - loop.getNumInductionVars(); + + // Check that the loop yields a broadcast that has just one use. + Operation *yieldedVal = + loop.getTiedLoopYieldedValue(blockArg)->get().getDefiningOp(); + auto broadcast = dyn_cast(yieldedVal); + if (!broadcast || !broadcast.getResult().hasOneUse()) + return WalkResult::advance(); + + LLVM_DEBUG(DBGS() << "Candidate broadcast: " << broadcast << "\n"); + + Type broadcastInputType = broadcast.getSourceType(); + if (broadcastInputType != extractOp.getType()) + return WalkResult::advance(); + + // The position of the extract must be defined outside of the loop if + // it is dynamic. + for (auto operand : extractOp.getDynamicPosition()) + if (!loop.isDefinedOutsideOfLoop(operand)) + return WalkResult::advance(); + + rewriter.modifyOpInPlace(broadcast, [&] { + extractOp.getVectorMutable().assign(initArg->get()); + }); + loop.moveOutOfLoop(extractOp); + rewriter.moveOpAfter(broadcast, loop); + + scf::ForOp newLoop = replaceWithDifferentYield( + rewriter, loop, extractOp.getResult(), index, broadcast.getSource()); + + LLVM_DEBUG(DBGS() << "New loop: " << newLoop << "\n"); + + rewriter.replaceAllUsesWith(newLoop.getResult(index), broadcast); + rewriter.modifyOpInPlace( + broadcast, [&] { broadcast.setOperand(newLoop.getResult(index)); }); + + changed = true; + return WalkResult::interrupt(); + }); + } +} + static bool noAliasingUseInLoop(vector::TransferReadOp transferRead, LoopLikeOpInterface loop) { Value source = transferRead.getSource(); diff --git a/mlir/test/Dialect/Linalg/hoisting.mlir b/mlir/test/Dialect/Linalg/hoisting.mlir index 550ffbc7bab6..241b8a486c01 100644 --- a/mlir/test/Dialect/Linalg/hoisting.mlir +++ b/mlir/test/Dialect/Linalg/hoisting.mlir @@ -565,3 +565,112 @@ module attributes {transform.with_named_sequence} { transform.yield } } + +// ----- + +// Test hoisting of vector.extract/vector.broadcast pairs + +// CHECK-LABEL: func.func @hoist_vector_broadcasts +// CHECK-SAME: (%{{.+}}: index, %{{.+}}: index, %{{.+}}: index, %[[VEC:.+]]: vector<3x4xf32>) -> vector<3x4xf32> { +// CHECK: %[[EXTRACT:.+]] = vector.extract %[[VEC]][0] : vector<4xf32> from vector<3x4xf32> +// CHECK-NEXT: %[[LOOP:.+]] = scf.for {{.*}} { +// CHECK-NEXT: %[[USE:.+]] = "some_use"({{.*}}) : (vector<4xf32>) -> vector<4xf32> +// CHECK-NEXT: scf.yield %[[USE]] : vector<4xf32> +// CHECK-NEXT: } +// CHECK-NEXT: %[[BCAST:.+]] = vector.broadcast %[[LOOP]] : vector<4xf32> to vector<3x4xf32> +// CHECK-NEXT: return %[[BCAST]] : vector<3x4xf32> + +func.func @hoist_vector_broadcasts(%lb : index, %ub : index, %step : index, %vec : vector<3x4xf32>) -> vector<3x4xf32> { + %bcast_vec = scf.for %arg0 = %lb to %ub step %step iter_args(%iarg = %vec) -> vector<3x4xf32> { + %extract = vector.extract %iarg[0] : vector<4xf32> from vector<3x4xf32> + %use = "some_use"(%extract) : (vector<4xf32>) -> vector<4xf32> + %broadcast = vector.broadcast %use : vector<4xf32> to vector<3x4xf32> + scf.yield %broadcast : vector<3x4xf32> + } + return %bcast_vec : vector<3x4xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["func.func"]} in %arg1 + : (!transform.any_op) -> !transform.any_op + transform.structured.hoist_redundant_vector_broadcasts %0 + : (!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +// Test hoisting of vector.extract/vector.broadcast pairs with dynamic position + +// CHECK-LABEL: func.func @hoist_vector_broadcasts +// CHECK-SAME: (%{{.+}}: index, %{{.+}}: index, %{{.+}}: index, %[[VEC:.+]]: vector<3x4xf32>, %[[POS:.+]]: index) -> vector<3x4xf32> { +// CHECK: %[[EXTRACT:.+]] = vector.extract %[[VEC]][%[[POS]]] : vector<4xf32> from vector<3x4xf32> +// CHECK-NEXT: %[[LOOP:.+]] = scf.for {{.*}} { +// CHECK-NEXT: %[[USE:.+]] = "some_use"({{.*}}) : (vector<4xf32>) -> vector<4xf32> +// CHECK-NEXT: scf.yield %[[USE]] : vector<4xf32> +// CHECK-NEXT: } +// CHECK-NEXT: %[[BCAST:.+]] = vector.broadcast %[[LOOP]] : vector<4xf32> to vector<3x4xf32> +// CHECK-NEXT: return %[[BCAST]] : vector<3x4xf32> + +func.func @hoist_vector_broadcasts_dynamic(%lb : index, %ub : index, %step : index, %vec : vector<3x4xf32>, %pos: index) -> vector<3x4xf32> { + %bcast_vec = scf.for %arg0 = %lb to %ub step %step iter_args(%iarg = %vec) -> vector<3x4xf32> { + %extract = vector.extract %iarg[%pos] : vector<4xf32> from vector<3x4xf32> + %use = "some_use"(%extract) : (vector<4xf32>) -> vector<4xf32> + %broadcast = vector.broadcast %use : vector<4xf32> to vector<3x4xf32> + scf.yield %broadcast : vector<3x4xf32> + } + return %bcast_vec : vector<3x4xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["func.func"]} in %arg1 + : (!transform.any_op) -> !transform.any_op + transform.structured.hoist_redundant_vector_broadcasts %0 + : (!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +// Test hoisting of vector.extract/vector.broadcast pairs with multiple iter_args + +// CHECK-LABEL: func.func @hoist_vector_broadcasts_multiple +// CHECK-SAME: (%{{.+}}: index, %{{.+}}: index, %{{.+}}: index, %[[VEC1:.+]]: vector<3x4xf32>, +// CHECK-SAME: %[[VEC2:.+]]: vector<3x5xf32>) -> (vector<3x4xf32>, vector<3x5xf32>) { +// CHECK-DAG: %[[EXTRACT1:.+]] = vector.extract %[[VEC1]][0] : vector<4xf32> from vector<3x4xf32> +// CHECK-DAG: %[[EXTRACT2:.+]] = vector.extract %[[VEC2]][1] : vector<5xf32> from vector<3x5xf32> +// CHECK-NEXT: %[[LOOP:.+]]:2 = scf.for {{.*}} { +// CHECK-DAG: %[[USE1:.+]] = "some_use1"({{.*}}) : (vector<4xf32>) -> vector<4xf32> +// CHECK-DAG: %[[USE2:.+]] = "some_use2"({{.*}}) : (vector<5xf32>) -> vector<5xf32> +// CHECK-NEXT: scf.yield %[[USE1]], %[[USE2]] : vector<4xf32>, vector<5xf32> +// CHECK-NEXT: } +// CHECK-DAG: %[[BCAST1:.+]] = vector.broadcast %[[LOOP]]#0 : vector<4xf32> to vector<3x4xf32> +// CHECK-DAG: %[[BCAST2:.+]] = vector.broadcast %[[LOOP]]#1 : vector<5xf32> to vector<3x5xf32> +// CHECK-NEXT: return %[[BCAST1]], %[[BCAST2]] : vector<3x4xf32>, vector<3x5xf32> + +func.func @hoist_vector_broadcasts_multiple(%lb : index, %ub : index, %step : index, %vec1 : vector<3x4xf32>, %vec2 : vector<3x5xf32>) -> (vector<3x4xf32>, vector<3x5xf32>) { + %bcast_vec:2 = scf.for %arg0 = %lb to %ub step %step iter_args(%iarg = %vec1, %iarg2 = %vec2) -> (vector<3x4xf32>, vector<3x5xf32>) { + %extract1 = vector.extract %iarg[0] : vector<4xf32> from vector<3x4xf32> + %extract2 = vector.extract %iarg2[1] : vector<5xf32> from vector<3x5xf32> + %use1 = "some_use1"(%extract1) : (vector<4xf32>) -> vector<4xf32> + %use2 = "some_use2"(%extract2) : (vector<5xf32>) -> vector<5xf32> + %broadcast1 = vector.broadcast %use1 : vector<4xf32> to vector<3x4xf32> + %broadcast2 = vector.broadcast %use2 : vector<5xf32> to vector<3x5xf32> + scf.yield %broadcast1, %broadcast2 : vector<3x4xf32>,vector<3x5xf32> + } + return %bcast_vec#0, %bcast_vec#1 : vector<3x4xf32>, vector<3x5xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["func.func"]} in %arg1 + : (!transform.any_op) -> !transform.any_op + transform.structured.hoist_redundant_vector_broadcasts %0 + : (!transform.any_op) -> !transform.any_op + transform.yield + } +} -- GitLab From c7e0f1e988d73555d1da7474528996e748622f42 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Mon, 22 Apr 2024 21:04:05 +0800 Subject: [PATCH 159/357] [X86] Allow input vector extracted from larger vector when combining to VPMADDUBSW (#89584) Failed on main trunk: https://godbolt.org/z/edWMz8chE --- llvm/lib/Target/X86/X86ISelLowering.cpp | 11 +++++++ llvm/test/CodeGen/X86/pmaddubsw.ll | 38 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 3a51c7c2ca85..dd40d079c7e2 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -51841,6 +51841,17 @@ static SDValue detectPMADDUBSW(SDValue In, EVT VT, SelectionDAG &DAG, return SDValue(); } + auto ExtractVec = [&DAG, &DL, NumElems](SDValue &Ext) { + EVT ExtVT = Ext.getValueType(); + if (ExtVT.getVectorNumElements() != NumElems * 2) { + MVT NVT = MVT::getVectorVT(MVT::i8, NumElems * 2); + Ext = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NVT, Ext, + DAG.getIntPtrConstant(0, DL)); + } + }; + ExtractVec(ZExtIn); + ExtractVec(SExtIn); + auto PMADDBuilder = [](SelectionDAG &DAG, const SDLoc &DL, ArrayRef Ops) { // Shrink by adding truncate nodes and let DAGCombine fold with the diff --git a/llvm/test/CodeGen/X86/pmaddubsw.ll b/llvm/test/CodeGen/X86/pmaddubsw.ll index e46a14673a51..d6c9877cd99b 100644 --- a/llvm/test/CodeGen/X86/pmaddubsw.ll +++ b/llvm/test/CodeGen/X86/pmaddubsw.ll @@ -469,3 +469,41 @@ define <8 x i16> @pmaddubsw_bad_indices(ptr %Aptr, ptr %Bptr) { %trunc = trunc <8 x i32> %min to <8 x i16> ret <8 x i16> %trunc } + +define <8 x i16> @pmaddubsw_large_vector(ptr %p1, ptr %p2) { +; SSE-LABEL: pmaddubsw_large_vector: +; SSE: # %bb.0: +; SSE-NEXT: movdqa (%rdi), %xmm0 +; SSE-NEXT: pmaddubsw (%rsi), %xmm0 +; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: pmaddubsw_large_vector: +; AVX: # %bb.0: +; AVX-NEXT: vmovdqa (%rdi), %xmm0 +; AVX-NEXT: vpmaddubsw (%rsi), %xmm0, %xmm0 +; AVX-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX-NEXT: vpblendw {{.*#+}} xmm0 = xmm1[0,1],xmm0[2],xmm1[3,4],xmm0[5],xmm1[6],xmm0[7] +; AVX-NEXT: retq + %1 = load <64 x i8>, ptr %p1, align 64 + %2 = shufflevector <64 x i8> %1, <64 x i8> poison, <8 x i32> + %3 = shufflevector <64 x i8> %1, <64 x i8> poison, <8 x i32> + %4 = load <32 x i8>, ptr %p2, align 64 + %5 = shufflevector <32 x i8> %4, <32 x i8> poison, <8 x i32> + %6 = shufflevector <32 x i8> %4, <32 x i8> poison, <8 x i32> + %7 = sext <8 x i8> %5 to <8 x i32> + %8 = zext <8 x i8> %2 to <8 x i32> + %9 = mul nsw <8 x i32> %7, %8 + %10 = sext <8 x i8> %6 to <8 x i32> + %11 = zext <8 x i8> %3 to <8 x i32> + %12 = mul nsw <8 x i32> %10, %11 + %13 = add nsw <8 x i32> %9, %12 + %14 = tail call <8 x i32> @llvm.smin.v8i32(<8 x i32> %13, <8 x i32> ) + %15 = tail call <8 x i32> @llvm.smax.v8i32(<8 x i32> %14, <8 x i32> ) + %16 = trunc <8 x i32> %15 to <8 x i16> + %17 = shufflevector <8 x i16> zeroinitializer, <8 x i16> %16, <8 x i32> + ret <8 x i16> %17 +} + +declare <8 x i32> @llvm.smin.v8i32(<8 x i32>, <8 x i32>) +declare <8 x i32> @llvm.smax.v8i32(<8 x i32>, <8 x i32>) -- GitLab From b099dd693c729e19b0343e4551bb764369997376 Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 22 Apr 2024 14:04:53 +0100 Subject: [PATCH 160/357] [AArch64] Add some tests for reassociated addressing modes. NFC --- llvm/test/CodeGen/AArch64/sve-reassocadd.ll | 184 ++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/sve-reassocadd.ll diff --git a/llvm/test/CodeGen/AArch64/sve-reassocadd.ll b/llvm/test/CodeGen/AArch64/sve-reassocadd.ll new file mode 100644 index 000000000000..47ddab8e2964 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-reassocadd.ll @@ -0,0 +1,184 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64 -mattr=+sve %s -o - | FileCheck %s + +define @i8_1v_4s(ptr %b) { +; CHECK-LABEL: i8_1v_4s: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: mov w9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1b { z0.b }, p0/z, [x8, x9] +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 4 + %add.ptr = getelementptr inbounds i8, ptr %b, i64 %1 + %add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 4 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i8_4s_1v(ptr %b) { +; CHECK-LABEL: i8_4s_1v: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: mov w9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1b { z0.b }, p0/z, [x8, x9] +; CHECK-NEXT: ret +entry: + %add.ptr = getelementptr inbounds i8, ptr %b, i64 4 + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 4 + %add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 %1 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i16_1v_8s(ptr %b) { +; CHECK-LABEL: i16_1v_8s: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1h { z0.h }, p0/z, [x8, x9, lsl #1] +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 3 + %add.ptr = getelementptr inbounds i16, ptr %b, i64 %1 + %add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 8 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i16_8s_1v(ptr %b) { +; CHECK-LABEL: i16_8s_1v: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1h { z0.h }, p0/z, [x8, x9, lsl #1] +; CHECK-NEXT: ret +entry: + %add.ptr = getelementptr inbounds i8, ptr %b, i64 8 + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 3 + %add.ptr1 = getelementptr inbounds i16, ptr %add.ptr, i64 %1 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i16_2v_8s(ptr %b) { +; CHECK-LABEL: i16_2v_8s: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #2 +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1h { z0.h }, p0/z, [x8, x9, lsl #1] +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 4 + %add.ptr = getelementptr inbounds i16, ptr %b, i64 %1 + %add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 8 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i16_8s_2v(ptr %b) { +; CHECK-LABEL: i16_8s_2v: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #2 +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1h { z0.h }, p0/z, [x8, x9, lsl #1] +; CHECK-NEXT: ret +entry: + %add.ptr = getelementptr inbounds i8, ptr %b, i64 8 + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 4 + %add.ptr1 = getelementptr inbounds i16, ptr %add.ptr, i64 %1 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i32_1v_16s(ptr %b) { +; CHECK-LABEL: i32_1v_16s: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1w { z0.s }, p0/z, [x8, x9, lsl #2] +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 2 + %add.ptr = getelementptr inbounds i32, ptr %b, i64 %1 + %add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 16 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i32_16s_2v(ptr %b) { +; CHECK-LABEL: i32_16s_2v: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1w { z0.s }, p0/z, [x8, x9, lsl #2] +; CHECK-NEXT: ret +entry: + %add.ptr = getelementptr inbounds i8, ptr %b, i64 16 + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 2 + %add.ptr1 = getelementptr inbounds i32, ptr %add.ptr, i64 %1 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i64_1v_32s(ptr %b) { +; CHECK-LABEL: i64_1v_32s: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x8, x9, lsl #3] +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 1 + %add.ptr = getelementptr inbounds i64, ptr %b, i64 %1 + %add.ptr1 = getelementptr inbounds i8, ptr %add.ptr, i64 32 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +define @i64_32s_2v(ptr %b) { +; CHECK-LABEL: i64_32s_2v: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: rdvl x8, #1 +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: mov x9, #4 // =0x4 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x8, x9, lsl #3] +; CHECK-NEXT: ret +entry: + %add.ptr = getelementptr inbounds i8, ptr %b, i64 32 + %0 = tail call i64 @llvm.vscale.i64() + %1 = shl nuw nsw i64 %0, 1 + %add.ptr1 = getelementptr inbounds i64, ptr %add.ptr, i64 %1 + %2 = load , ptr %add.ptr1, align 16 + ret %2 +} + +declare i64 @llvm.vscale.i64() -- GitLab From 0accda7f17a1f85b4270edf4f0976c55de4e958c Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Mon, 22 Apr 2024 09:08:27 -0400 Subject: [PATCH 161/357] [Clang] Fix a crash introduced in PR#88666 (#89567) --- clang/lib/Sema/SemaStmtAttr.cpp | 2 +- clang/test/Sema/unroll-template-value-crash.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 clang/test/Sema/unroll-template-value-crash.cpp diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 7cd494b42250..9d44c22c8ddc 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -109,7 +109,7 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable); } else if (PragmaName == "unroll") { // #pragma unroll N - if (ValueExpr) { + if (ValueExpr && !ValueExpr->isValueDependent()) { llvm::APSInt ValueAPS; ExprResult R = S.VerifyIntegerConstantExpression(ValueExpr, &ValueAPS); assert(!R.isInvalid() && "unroll count value must be a valid value, it's " diff --git a/clang/test/Sema/unroll-template-value-crash.cpp b/clang/test/Sema/unroll-template-value-crash.cpp new file mode 100644 index 000000000000..d8953c4845c2 --- /dev/null +++ b/clang/test/Sema/unroll-template-value-crash.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -x c++ -verify %s +// expected-no-diagnostics + +template void foo() { + #pragma unroll Unroll + for (int i = 0; i < Unroll; ++i); + + #pragma GCC unroll Unroll + for (int i = 0; i < Unroll; ++i); +} -- GitLab From fe28a0e4823f59d193a14a07d12e3f60555350e0 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 22 Apr 2024 14:10:05 +0100 Subject: [PATCH 162/357] [LAA] Document reasoning in multiple places in isDependent (NFC). (#89381) As suggested in https://github.com/llvm/llvm-project/pull/88039, add extra documentation for reasoning in isDependent. PR: https://github.com/llvm/llvm-project/pull/89381 --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index 3bfc9700a145..b1ba8e7c0f60 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -2034,6 +2034,10 @@ MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent( ScalarEvolution &SE = *PSE.getSE(); auto &DL = InnermostLoop->getHeader()->getModule()->getDataLayout(); + // If the distance between the acecsses is larger than their absolute stride + // multiplied by the backedge taken count, the accesses are independet, i.e. + // they are far enough appart that accesses won't access the same location + // across all loop ierations. if (!isa(Dist) && HasSameSize && isSafeDependenceDistance(DL, SE, *(PSE.getBackedgeTakenCount()), *Dist, Stride, TypeByteSize)) @@ -2049,7 +2053,8 @@ MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent( const APInt &Val = C->getAPInt(); int64_t Distance = Val.getSExtValue(); - // Attempt to prove strided accesses independent. + // If the distance between accesses and their strides are known constants, + // check whether the accesses interlace each other. if (std::abs(Distance) > 0 && Stride > 1 && HasSameSize && areStridedAccessesIndependent(std::abs(Distance), Stride, TypeByteSize)) { LLVM_DEBUG(dbgs() << "LAA: Strided accesses are independent\n"); @@ -2059,9 +2064,13 @@ MemoryDepChecker::Dependence::DepType MemoryDepChecker::isDependent( // Negative distances are not plausible dependencies. if (Val.isNegative()) { bool IsTrueDataDependence = (AIsWrite && !BIsWrite); - // There is no need to update MaxSafeVectorWidthInBits after call to - // couldPreventStoreLoadForward, even if it changed MinDepDistBytes, - // since a forward dependency will allow vectorization using any width. + // Check if the first access writes to a location that is read in a later + // iteration, where the distance between them is not a multiple of a vector + // factor and relatively small. + // + // NOTE: There is no need to update MaxSafeVectorWidthInBits after call to + // couldPreventStoreLoadForward, even if it changed MinDepDistBytes, since a + // forward dependency will allow vectorization using any width. if (IsTrueDataDependence && EnableForwardingConflictDetection && (!HasSameSize || couldPreventStoreLoadForward(Val.abs().getZExtValue(), TypeByteSize))) { -- GitLab From 5198923c70bb5b91b07e15ce141339d778322635 Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Mon, 22 Apr 2024 10:19:42 -0300 Subject: [PATCH 163/357] [flang][OpenMP] Allow common blocks in nested directives (#88430) COMMON block names must be declared in the same scoping unit in which the OpenMP directive or clause appears, but OpenMP constructs must not be considered as scoping units. Instead, consider only program units and block constructs as such. --- flang/lib/Semantics/resolve-directives.cpp | 13 ++++------- flang/test/Semantics/OpenMP/resolve03.f90 | 25 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index f4ac7f198d85..318687508ff1 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2096,15 +2096,10 @@ Symbol *OmpAttributeVisitor::ResolveOmpCommonBlockName( if (!name) { return nullptr; } - // First check if the Common Block is declared in the current scope - if (auto *cur{GetContext().scope.FindCommonBlock(name->source)}) { - name->symbol = cur; - return cur; - } - // Then check parent scope - if (auto *prev{GetContext().scope.parent().FindCommonBlock(name->source)}) { - name->symbol = prev; - return prev; + if (auto *cb{GetProgramUnitOrBlockConstructContaining(GetContext().scope) + .FindCommonBlock(name->source)}) { + name->symbol = cb; + return cb; } return nullptr; } diff --git a/flang/test/Semantics/OpenMP/resolve03.f90 b/flang/test/Semantics/OpenMP/resolve03.f90 index b9306c4fe9cb..ebc66ca12ebf 100644 --- a/flang/test/Semantics/OpenMP/resolve03.f90 +++ b/flang/test/Semantics/OpenMP/resolve03.f90 @@ -8,6 +8,9 @@ common /c/ a, b integer a(3), b + common /tc/ x + integer x + !$omp threadprivate(/tc/) A = 1 B = 2 @@ -19,4 +22,26 @@ !$omp end parallel end block print *, a, b + + !$omp parallel + block + !$omp single + x = 18 + !ERROR: COMMON block must be declared in the same scoping unit in which the OpenMP directive or clause appears + !$omp end single copyprivate(/tc/) + end block + !$omp end parallel + + ! Common block names may be used inside nested OpenMP directives. + !$omp parallel + !$omp parallel copyin(/tc/) + x = x + 10 + !$omp end parallel + !$omp end parallel + + !$omp parallel + !$omp single + x = 18 + !$omp end single copyprivate(/tc/) + !$omp end parallel end -- GitLab From 36c8af66e08e10b42e964765c9b24dcc60fdf4c0 Mon Sep 17 00:00:00 2001 From: Alex Zinenko Date: Mon, 22 Apr 2024 13:22:07 +0000 Subject: [PATCH 164/357] [mlir] fix polynomial dialect docs Some docs were emitted into the wrong location (Polynomial/ instead of Dialect/). Furthermore, `-gen-dialect-docs` subsumes `-gen-attr/typedef-docs` so the latter are not required. Add a top-level entry that includes both other files in a proper order. --- mlir/docs/Dialects/Polynomial.md | 2 ++ mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 mlir/docs/Dialects/Polynomial.md diff --git a/mlir/docs/Dialects/Polynomial.md b/mlir/docs/Dialects/Polynomial.md new file mode 100644 index 000000000000..6fdd74ab30aa --- /dev/null +++ b/mlir/docs/Dialects/Polynomial.md @@ -0,0 +1,2 @@ +[include "Dialects/PolynomialDialect.td"] +[include "Dialects/PolynomialOps.td"] diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt index 79e739953d7c..c8655ba99870 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt @@ -1,8 +1,6 @@ add_mlir_dialect(Polynomial polynomial) -add_mlir_doc(Polynomial PolynomialDialect Polynomial/ -gen-dialect-doc -dialect=polynomial) -add_mlir_doc(Polynomial PolynomialOps Polynomial/ -gen-op-doc) -add_mlir_doc(Polynomial PolynomialAttributes Dialects/ -gen-attrdef-doc) -add_mlir_doc(Polynomial PolynomialTypes Dialects/ -gen-typedef-doc) +add_mlir_doc(Polynomial PolynomialDialect Dialects/ -gen-dialect-doc -dialect=polynomial) +add_mlir_doc(Polynomial PolynomialOps Dialects/ -gen-op-doc) set(LLVM_TARGET_DEFINITIONS Polynomial.td) mlir_tablegen(PolynomialAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=polynomial) -- GitLab From 024c3d0c079fd9297725c35082316f2ca29c9526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 13:31:40 +0200 Subject: [PATCH 165/357] [clang][Interp][NFC] Refactor Program::getGlobal() Move the iterator declarations into the if statements and return std::nullopt explicitly. --- clang/lib/AST/Interp/Program.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 2c8c6781b348..7bf842f1a940 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -108,27 +108,23 @@ Pointer Program::getPtrGlobal(unsigned Idx) const { } std::optional Program::getGlobal(const ValueDecl *VD) { - auto It = GlobalIndices.find(VD); - if (It != GlobalIndices.end()) + if (auto It = GlobalIndices.find(VD); It != GlobalIndices.end()) return It->second; // Find any previous declarations which were already evaluated. std::optional Index; - for (const Decl *P = VD; P; P = P->getPreviousDecl()) { - auto It = GlobalIndices.find(P); - if (It != GlobalIndices.end()) { + for (const Decl *P = VD->getPreviousDecl(); P; P = P->getPreviousDecl()) { + if (auto It = GlobalIndices.find(P); It != GlobalIndices.end()) { Index = It->second; break; } } // Map the decl to the existing index. - if (Index) { + if (Index) GlobalIndices[VD] = *Index; - return std::nullopt; - } - return Index; + return std::nullopt; } std::optional Program::getOrCreateGlobal(const ValueDecl *VD, -- GitLab From abca85b3f7d5d3a1ae8dfea37d41e913c67b9bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 13:32:30 +0200 Subject: [PATCH 166/357] [clang][Interp] Remove faulty assertion The assertion doesn't work if there are multiple declarations for a variable involved. --- clang/lib/AST/Interp/Program.cpp | 1 - clang/test/AST/Interp/literals.cpp | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 7bf842f1a940..3773e0662f78 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -169,7 +169,6 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { std::optional Program::createGlobal(const ValueDecl *VD, const Expr *Init) { - assert(!getGlobal(VD)); bool IsStatic, IsExtern; if (const auto *Var = dyn_cast(VD)) { IsStatic = Context::shouldBeGloballyIndexed(VD); diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 277438d2e631..2688b53adde2 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -1209,4 +1209,16 @@ constexpr int externvar1() { // both-error {{never produces a constant expressio namespace Extern { constexpr extern char Oops = 1; static_assert(Oops == 1, ""); + +#if __cplusplus >= 201402L + struct NonLiteral { + NonLiteral() {} + }; + NonLiteral nl; + constexpr NonLiteral &ExternNonLiteralVarDecl() { + extern NonLiteral nl; + return nl; + } + static_assert(&ExternNonLiteralVarDecl() == &nl, ""); +#endif } -- GitLab From 5ef5eb66fb428aaf61fb51b709f065c069c11242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 22 Apr 2024 15:27:15 +0200 Subject: [PATCH 167/357] [clang][Interp] Implement C++23 [[assume]] support --- clang/lib/AST/Interp/ByteCodeStmtGen.cpp | 25 +++++++++++++++++++++++- clang/lib/AST/Interp/Interp.h | 12 ++++++++++++ clang/lib/AST/Interp/Opcodes.td | 2 ++ clang/test/SemaCXX/cxx23-assume.cpp | 2 ++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index 55a06f37a0c3..36dab6252ece 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -675,7 +675,30 @@ bool ByteCodeStmtGen::visitDefaultStmt(const DefaultStmt *S) { template bool ByteCodeStmtGen::visitAttributedStmt(const AttributedStmt *S) { - // Ignore all attributes. + + for (const Attr *A : S->getAttrs()) { + auto *AA = dyn_cast(A); + if (!AA) + continue; + + assert(isa(S->getSubStmt())); + + const Expr *Assumption = AA->getAssumption(); + if (Assumption->isValueDependent()) + return false; + + if (Assumption->HasSideEffects(this->Ctx.getASTContext())) + continue; + + // Evaluate assumption. + if (!this->visitBool(Assumption)) + return false; + + if (!this->emitAssume(Assumption)) + return false; + } + + // Ignore other attributes. return this->visitStmt(S->getSubStmt()); } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index d593d764d85a..9283f697c007 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2327,6 +2327,18 @@ inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, return CheckDeclRef(S, OpPC, DR); } +inline bool Assume(InterpState &S, CodePtr OpPC) { + const auto Val = S.Stk.pop(); + + if (Val) + return true; + + // Else, diagnose. + const SourceLocation &Loc = S.Current->getLocation(OpPC); + S.CCEDiag(Loc, diag::note_constexpr_assumption_failed); + return false; +} + template ::T> inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) { llvm::SmallVector ArrayIndices; diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 0a6c976f9b5b..742785b28eb4 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -736,6 +736,8 @@ def InvalidDeclRef : Opcode { let Args = [ArgDeclRef]; } +def Assume : Opcode; + def ArrayDecay : Opcode; def CheckNonNullArg : Opcode { diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index 478da092471a..8676970de14f 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -std=c++23 -x c++ %s -verify // RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected +// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected -fexperimental-new-constant-interpreter struct A{}; struct B{ explicit operator bool() { return true; } }; -- GitLab From ef1d19b0a58f92241963a1403905e8b0a8484b5f Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 22 Apr 2024 06:36:52 -0700 Subject: [PATCH 168/357] [SLP]Fix PR89438: check for all tree entries for the resized value. Need to check all possible entries, before trying looking for the minbitwidth in the user node. Otherwise we may incorrectly get signedness info. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 68 +++++++++----- .../X86/gather-node-same-reduced.ll | 92 +++++++++++++++++++ 2 files changed, 138 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 1b56bb7b600c..e70612ae49f7 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13139,31 +13139,55 @@ Value *BoUpSLP::vectorizeTree( assert(Vec->getType()->isIntOrIntVectorTy() && PrevVec->getType()->isIntOrIntVectorTy() && "Expected integer vector types only."); - std::optional> Res; - if (const TreeEntry *BaseTE = getTreeEntry(TE->Scalars.front())) { - SmallVector BaseTEs; - if (BaseTE->isSame(TE->Scalars)) - BaseTEs.push_back(BaseTE); - auto It = MultiNodeScalars.find(TE->Scalars.front()); - if (It != MultiNodeScalars.end()) { - for (const TreeEntry *MNTE : It->getSecond()) - if (MNTE->isSame(TE->Scalars)) - BaseTEs.push_back(MNTE); + std::optional IsSigned; + for (Value *V : TE->Scalars) { + if (const TreeEntry *BaseTE = getTreeEntry(V)) { + auto It = MinBWs.find(BaseTE); + if (It != MinBWs.end()) { + IsSigned = IsSigned.value_or(false) || It->second.second; + if (*IsSigned) + break; + } + for (const TreeEntry *MNTE : MultiNodeScalars.lookup(V)) { + auto It = MinBWs.find(MNTE); + if (It != MinBWs.end()) { + IsSigned = IsSigned.value_or(false) || It->second.second; + if (*IsSigned) + break; + } + } + if (IsSigned.value_or(false)) + break; + // Scan through gather nodes. + for (const TreeEntry *BVE : ValueToGatherNodes.lookup(V)) { + auto It = MinBWs.find(BVE); + if (It != MinBWs.end()) { + IsSigned = IsSigned.value_or(false) || It->second.second; + if (*IsSigned) + break; + } + } + if (IsSigned.value_or(false)) + break; + if (auto *EE = dyn_cast(V)) { + IsSigned = + IsSigned.value_or(false) || + !isKnownNonNegative(EE->getVectorOperand(), SimplifyQuery(*DL)); + continue; + } + if (IsSigned.value_or(false)) + break; } - const auto *BaseIt = find_if(BaseTEs, [&](const TreeEntry *BaseTE) { - return MinBWs.contains(BaseTE); - }); - if (BaseIt != BaseTEs.end()) - Res = MinBWs.lookup(*BaseIt); } - if (!Res) { - assert(MinBWs.contains(TE->UserTreeIndices.front().UserTE) && - "Expected user in MinBWs."); - Res = MinBWs.lookup(TE->UserTreeIndices.front().UserTE); + if (IsSigned.value_or(false)) { + // Final attempt - check user node. + auto It = MinBWs.find(TE->UserTreeIndices.front().UserTE); + if (It != MinBWs.end()) + IsSigned = It->second.second; } - assert(Res && "Expected user node or perfect diamond match in MinBWs."); - bool IsSigned = Res->second; - Vec = Builder.CreateIntCast(Vec, PrevVec->getType(), IsSigned); + assert(IsSigned && + "Expected user node or perfect diamond match in MinBWs."); + Vec = Builder.CreateIntCast(Vec, PrevVec->getType(), *IsSigned); } PrevVec->replaceAllUsesWith(Vec); PostponedValues.try_emplace(Vec).first->second.push_back(TE); diff --git a/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll b/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll index b03eb9e67254..42ed26d82e03 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/gather-node-same-reduced.ll @@ -82,3 +82,95 @@ define i64 @test(ptr %p) { store i8 %55, ptr %3, align 1 ret i64 0 } + +define i64 @test1(ptr %p) { +; CHECK-LABEL: define i64 @test1( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P]], i64 12 +; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i32> zeroinitializer, zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = xor <4 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i32> [[TMP3]], zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = xor <4 x i32> [[TMP4]], zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = xor <4 x i32> [[TMP5]], zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i32> [[TMP6]], zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i32> [[TMP7]], zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = xor <4 x i32> [[TMP8]], zeroinitializer +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i32> [[TMP9]], zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = xor <4 x i32> [[TMP10]], zeroinitializer +; CHECK-NEXT: [[TMP12:%.*]] = trunc <4 x i32> [[TMP11]] to <4 x i8> +; CHECK-NEXT: store <4 x i8> [[TMP12]], ptr [[TMP1]], align 1 +; CHECK-NEXT: ret i64 0 +; + %1 = getelementptr i8, ptr %p, i64 13 + %2 = getelementptr i8, ptr %p, i64 14 + %3 = getelementptr i8, ptr %p, i64 15 + %4 = getelementptr i8, ptr %p, i64 12 + %5 = zext i8 0 to i32 + %6 = and i32 %5, 0 + %.not866 = icmp eq i32 %6, 0 + %7 = select i1 %.not866, i32 0, i32 0 + %8 = xor i32 0, %7 + %9 = zext i8 0 to i32 + %10 = and i32 %9, 0 + %.not869 = icmp eq i32 %10, 0 + %11 = select i1 %.not869, i32 0, i32 0 + %12 = xor i32 0, %11 + %13 = zext i8 0 to i32 + %14 = and i32 %13, 0 + %.not871 = icmp eq i32 %14, 0 + %15 = select i1 %.not871, i32 0, i32 0 + %16 = xor i32 0, %15 + %17 = zext i8 0 to i32 + %18 = and i32 %17, 0 + %.not874 = icmp eq i32 %18, 0 + %19 = select i1 %.not874, i32 0, i32 0 + %20 = xor i32 0, %19 + %21 = xor i32 %13, 0 + %22 = xor i32 %21, 0 + %23 = xor i32 %22, 0 + %24 = xor i32 %23, 0 + %25 = xor i32 %24, 0 + %26 = xor i32 %25, 0 + %27 = xor i32 %26, %8 + %28 = xor i32 %27, 0 + %29 = xor i32 %28, 0 + %30 = xor i32 %29, 0 + %31 = trunc i32 %30 to i8 + store i8 %31, ptr %4, align 1 + %32 = xor i32 %13, 0 + %33 = xor i32 %32, 0 + %34 = xor i32 %33, 0 + %35 = xor i32 %34, 0 + %36 = xor i32 %35, 0 + %37 = xor i32 %36, 0 + %38 = xor i32 %37, %20 + %39 = xor i32 %38, 0 + %40 = xor i32 %39, 0 + %41 = xor i32 %40, 0 + %42 = trunc i32 %41 to i8 + store i8 %42, ptr %1, align 1 + %43 = xor i32 %9, 0 + %44 = xor i32 %43, 0 + %45 = xor i32 %44, 0 + %46 = xor i32 %45, 0 + %47 = xor i32 %46, 0 + %48 = xor i32 %47, 0 + %49 = xor i32 %48, %16 + %50 = xor i32 %49, 0 + %51 = xor i32 %50, 0 + %52 = xor i32 %51, 0 + %53 = trunc i32 %52 to i8 + store i8 %53, ptr %2, align 1 + %54 = xor i32 %43, 0 + %55 = xor i32 %54, 0 + %56 = xor i32 %55, 0 + %57 = xor i32 %56, 0 + %58 = xor i32 %57, 0 + %59 = xor i32 %58, %12 + %60 = xor i32 %59, 0 + %61 = xor i32 %60, 0 + %62 = xor i32 %61, 0 + %63 = trunc i32 %62 to i8 + store i8 %63, ptr %3, align 1 + ret i64 0 +} -- GitLab From 1fb3ea6ded051e1e78aed96435b830920b59ac56 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 22 Apr 2024 10:00:32 -0400 Subject: [PATCH 169/357] [gn] port e86ebe4ff870 (llvm-split target dep) --- llvm/utils/gn/secondary/llvm/tools/llvm-split/BUILD.gn | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-split/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-split/BUILD.gn index f37e75aad0a5..f2c24ea4421b 100644 --- a/llvm/utils/gn/secondary/llvm/tools/llvm-split/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-split/BUILD.gn @@ -1,9 +1,16 @@ executable("llvm-split") { deps = [ "//llvm/lib/Bitcode/Writer", + "//llvm/lib/CodeGen", "//llvm/lib/IR", "//llvm/lib/IRReader", + "//llvm/lib/MC", "//llvm/lib/Support", + "//llvm/lib/Target", + "//llvm/lib/Target:AllTargetsAsmParsers", + "//llvm/lib/Target:AllTargetsCodeGens", + "//llvm/lib/Target:AllTargetsDescs", + "//llvm/lib/Target:AllTargetsInfos", "//llvm/lib/Transforms/Utils", ] sources = [ "llvm-split.cpp" ] -- GitLab From 9803196849bd9c473aba7ead03da9aee5591f373 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 22 Apr 2024 10:14:54 -0400 Subject: [PATCH 170/357] [libc++][NFC] Fix unparenthesized comma expression in mem-initializer (#89605) #84050 resolves class member access expressions naming members of the current instantiation prior to instantiation. In testing, it has revealed a mem-initializer in the move constructor of `invocable_with_telemetry` that uses an unparenthesized comma expression to initialize a non-static data member of pointer type. This patch fixes it. --- libcxx/test/support/invocable_with_telemetry.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/support/invocable_with_telemetry.h b/libcxx/test/support/invocable_with_telemetry.h index 612bbec639d4..e010837a1624 100644 --- a/libcxx/test/support/invocable_with_telemetry.h +++ b/libcxx/test/support/invocable_with_telemetry.h @@ -31,7 +31,7 @@ public: constexpr invocable_with_telemetry(invocable_with_telemetry&& other) requires std::move_constructible : f_(std::move(other.f_)), - telemetry_(assert(other.telemetry_ != nullptr), std::exchange(other.telemetry_, nullptr)) { + telemetry_((assert(other.telemetry_ != nullptr), std::exchange(other.telemetry_, nullptr))) { ++telemetry_->moves; } -- GitLab From 9ef9db7087fe6ce00a84f1456fce9f2e98db0769 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Mon, 22 Apr 2024 10:17:26 -0400 Subject: [PATCH 171/357] [lldb][DWARF] Remove m_forward_decl_die_to_compiler_type as it never actually being used. (#89427) This removes `m_forward_decl_die_to_compiler_type` which is a map from `const DWARFDebugInfoEntry *` to `lldb::opaque_compiler_type_t`. This map is currently used in `DWARFASTParserClang::ParseEnum` and `DWARFASTParserClang::ParseStructureLikeDIE` to avoid creating duplicate CompilerType for the specific DIE. But before entering these two functions in `DWARFASTParserClang::ParseTypeFromDWARF`, we already checked with `SymbolFileDWARF::GetDIEToType()` if we have a Type created from this DIE to avoid trying to parse the same DIE twice. So, this map is unnecessary and not useful. --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 148 ++++++++---------- .../SymbolFile/DWARF/SymbolFileDWARF.h | 9 -- .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 5 - .../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 2 - 4 files changed, 65 insertions(+), 99 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 54d06b1115a2..41d81fbcf1b0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -854,36 +854,26 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, DW_TAG_value_to_name(tag), type_name_cstr); CompilerType enumerator_clang_type; - CompilerType clang_type; - clang_type = CompilerType( - m_ast.weak_from_this(), - dwarf->GetForwardDeclDIEToCompilerType().lookup(die.GetDIE())); - if (!clang_type) { - if (attrs.type.IsValid()) { - Type *enumerator_type = - dwarf->ResolveTypeUID(attrs.type.Reference(), true); - if (enumerator_type) - enumerator_clang_type = enumerator_type->GetFullCompilerType(); - } + if (attrs.type.IsValid()) { + Type *enumerator_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); + if (enumerator_type) + enumerator_clang_type = enumerator_type->GetFullCompilerType(); + } - if (!enumerator_clang_type) { - if (attrs.byte_size) { - enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - "", DW_ATE_signed, *attrs.byte_size * 8); - } else { - enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); - } + if (!enumerator_clang_type) { + if (attrs.byte_size) { + enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( + "", DW_ATE_signed, *attrs.byte_size * 8); + } else { + enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); } - - clang_type = m_ast.CreateEnumerationType( - attrs.name.GetStringRef(), - GetClangDeclContextContainingDIE(die, nullptr), - GetOwningClangModule(die), attrs.decl, enumerator_clang_type, - attrs.is_scoped_enum); - } else { - enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type); } + CompilerType clang_type = m_ast.CreateEnumerationType( + attrs.name.GetStringRef(), GetClangDeclContextContainingDIE(die, nullptr), + GetOwningClangModule(die), attrs.decl, enumerator_clang_type, + attrs.is_scoped_enum); + LinkDeclContextToDIE(TypeSystemClang::GetDeclContextForType(clang_type), die); type_sp = @@ -1781,65 +1771,59 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, assert(tag_decl_kind != -1); UNUSED_IF_ASSERT_DISABLED(tag_decl_kind); bool clang_type_was_created = false; - clang_type = CompilerType( - m_ast.weak_from_this(), - dwarf->GetForwardDeclDIEToCompilerType().lookup(die.GetDIE())); - if (!clang_type) { - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - - PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die, - attrs.name.GetCString()); - - if (attrs.accessibility == eAccessNone && decl_ctx) { - // Check the decl context that contains this class/struct/union. If - // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass(containing_decl_kind)) - attrs.accessibility = default_accessibility; - } - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - - TypeSystemClang::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl( - decl_ctx, GetOwningClangModule(die), attrs.accessibility, - attrs.name.GetCString(), tag_decl_kind, template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - return TypeSP(); - } + clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, GetOwningClangModule(die), class_template_decl, - tag_decl_kind, template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; + PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die, + attrs.name.GetCString()); - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } + if (attrs.accessibility == eAccessNone && decl_ctx) { + // Check the decl context that contains this class/struct/union. If + // it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass(containing_decl_kind)) + attrs.accessibility = default_accessibility; + } + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - if (!clang_type_was_created) { - clang_type_was_created = true; - clang_type = m_ast.CreateRecordType( - decl_ctx, GetOwningClangModule(die), attrs.accessibility, - attrs.name.GetCString(), tag_decl_kind, attrs.class_language, - &metadata, attrs.exports_symbols); + TypeSystemClang::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl( + decl_ctx, GetOwningClangModule(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, template_param_infos); + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); + } + return TypeSP(); } + + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, GetOwningClangModule(die), class_template_decl, + tag_decl_kind, template_param_infos); + clang_type = + m_ast.CreateClassTemplateSpecializationType(class_specialization_decl); + clang_type_was_created = true; + + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); + } + + if (!clang_type_was_created) { + clang_type_was_created = true; + clang_type = m_ast.CreateRecordType( + decl_ctx, GetOwningClangModule(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata, + attrs.exports_symbols); } // Store a forward declaration to this class type in case any @@ -1924,8 +1908,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // Can't assume m_ast.GetSymbolFile() is actually a // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple // binaries. - dwarf->GetForwardDeclDIEToCompilerType()[die.GetDIE()] = - clang_type.GetOpaqueQualType(); dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), *die.GetDIERef()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 2f8f80f8765c..7282c08c6857 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -335,14 +335,6 @@ public: virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; } - typedef llvm::DenseMap - DIEToCompilerType; - - virtual DIEToCompilerType &GetForwardDeclDIEToCompilerType() { - return m_forward_decl_die_to_compiler_type; - } - typedef llvm::DenseMap CompilerTypeToDIE; @@ -543,7 +535,6 @@ protected: UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; - DIEToCompilerType m_forward_decl_die_to_compiler_type; CompilerTypeToDIE m_forward_decl_compiler_type_to_die; llvm::DenseMap> m_type_unit_support_files; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index a0a7012dfaf0..85e1afd0d897 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -110,11 +110,6 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() { return GetBaseSymbolFile().GetDIEToVariable(); } -SymbolFileDWARF::DIEToCompilerType & -SymbolFileDWARFDwo::GetForwardDeclDIEToCompilerType() { - return GetBaseSymbolFile().GetForwardDeclDIEToCompilerType(); -} - SymbolFileDWARF::CompilerTypeToDIE & SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() { return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index c2c420f711d3..1500540424b5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -72,8 +72,6 @@ protected: DIEToVariableSP &GetDIEToVariable() override; - DIEToCompilerType &GetForwardDeclDIEToCompilerType() override; - CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override; UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override; -- GitLab From 70abbd9084e25d2485edfeb252b603b3910a23bc Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 22 Apr 2024 16:28:14 +0200 Subject: [PATCH 172/357] [AST] Dump argument types for TypeTraitExpr. (#89370) The argument types are not modeled as children of TypeTraitExpr, therefore they are not dumped with the default implementation. Dumping them is really useful for ad-hoc debugging, context #89358 --- clang/include/clang/AST/ASTNodeTraverser.h | 6 +++ ...dump-template-json-win32-mangler-crash.cpp | 40 ++++++++++++++++++- clang/test/AST/ast-dump-traits.cpp | 9 +++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index f5c47d8a7c21..216dc9eef08b 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -851,6 +851,12 @@ public: Visit(R); } + void VisitTypeTraitExpr(const TypeTraitExpr *E) { + // Argument types are not children of the TypeTraitExpr. + for (auto *A : E->getArgs()) + Visit(A->getType()); + } + void VisitLambdaExpr(const LambdaExpr *Node) { if (Traversal == TK_IgnoreUnlessSpelledInSource) { for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp index 8c03b58abb0e..cf740516db6f 100644 --- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp +++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp @@ -2725,7 +2725,25 @@ int main() // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "bool" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue" +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } @@ -3003,7 +3021,25 @@ int main() // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "bool" // CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue" +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-traits.cpp b/clang/test/AST/ast-dump-traits.cpp index 99ad50f528eb..3085e5883fd2 100644 --- a/clang/test/AST/ast-dump-traits.cpp +++ b/clang/test/AST/ast-dump-traits.cpp @@ -40,10 +40,19 @@ void test_unary_expr_or_type_trait() { // CHECK-NEXT: | | `-EnumDecl {{.*}} col:8{{( imported)?}} referenced E // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_enum +// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'E' sugar +// CHECK-NEXT: | | `-EnumType {{.*}} 'E' +// CHECK-NEXT: | | `-Enum {{.*}} 'E' // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_same +// CHECK-NEXT: | | |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: | | `-BuiltinType {{.*}} 'float' // CHECK-NEXT: | `-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | `-TypeTraitExpr {{.*}} 'bool' __is_constructible +// CHECK-NEXT: |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: |-BuiltinType {{.*}} 'int' +// CHECK-NEXT: `-BuiltinType {{.*}} 'int' // CHECK-NEXT: |-FunctionDecl {{.*}} line:20:6{{( imported)?}} test_array_type_trait 'void ()' // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: | `-CStyleCastExpr {{.*}} 'void' -- GitLab From 5138ccd0e479d1702c2adefe1cd611e1aebe2f8b Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 22 Apr 2024 15:50:58 +0100 Subject: [PATCH 173/357] [LAA] Add etra tests with strides with different signs. Extra tests with strides with different signs for https://github.com/llvm/llvm-project/pull/88039. --- .../non-constant-strides-forward.ll | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) diff --git a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll index aa22a2143352..51755314896b 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll @@ -180,3 +180,234 @@ loop: exit: ret void } + +; Tests with accesses with strides with different signs. +define void @strides_with_different_directions_1(ptr %A) { +; CHECK-LABEL: 'strides_with_different_directions_1' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + br label %loop + +loop: + %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] + %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] + %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.1 + %l = load i32, ptr %gep.mul.2, align 4 + %add = add nsw i32 %l, 5 + %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2 + store i32 %add, ptr %gep, align 4 + %iv.1.next = add nuw nsw i64 %iv.1, 1 + %iv.2.next = add nsw i64 %iv.2, -1 + %exitcond.not = icmp eq i64 %iv.1.next, 256 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @strides_with_different_directions_2(ptr %A) { +; CHECK-LABEL: 'strides_with_different_directions_2' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + br label %loop + +loop: + %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] + %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] + %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.2 + %l = load i32, ptr %gep.mul.2, align 4 + %add = add nsw i32 %l, 5 + %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1 + store i32 %add, ptr %gep, align 4 + %iv.1.next = add nuw nsw i64 %iv.1, 1 + %iv.2.next = add nsw i64 %iv.2, -1 + %exitcond.not = icmp eq i64 %iv.1.next, 256 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @strides_with_different_directions_3(ptr %A) { +; CHECK-LABEL: 'strides_with_different_directions_3' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + br label %loop + +loop: + %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] + %iv.2 = phi i64 [ 600, %entry ], [ %iv.2.next, %loop ] + %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.1 + %l = load i32, ptr %gep.mul.2, align 4 + %add = add nsw i32 %l, 5 + %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2 + store i32 %add, ptr %gep, align 4 + %iv.1.next = add nuw nsw i64 %iv.1, 1 + %iv.2.next = add nsw i64 %iv.2, -2 + %exitcond.not = icmp eq i64 %iv.1.next, 256 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @strides_with_different_directions_4(ptr %A) { +; CHECK-LABEL: 'strides_with_different_directions_4' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + br label %loop + +loop: + %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] + %iv.2 = phi i64 [ 600, %entry ], [ %iv.2.next, %loop ] + %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.2 + %l = load i32, ptr %gep.mul.2, align 4 + %add = add nsw i32 %l, 5 + %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1 + store i32 %add, ptr %gep, align 4 + %iv.1.next = add nuw nsw i64 %iv.1, 1 + %iv.2.next = add nsw i64 %iv.2, -2 + %exitcond.not = icmp eq i64 %iv.1.next, 256 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @non_constant_strides_with_different_directions_1(ptr %A) { +; CHECK-LABEL: 'non_constant_strides_with_different_directions_1' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + br label %loop + +loop: + %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] + %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] + %iv.mul.2 = shl nuw nsw i64 %iv.1, 1 + %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 + %l = load i32, ptr %gep.mul.2, align 4 + %add = add nsw i32 %l, 5 + %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2 + store i32 %add, ptr %gep, align 4 + %iv.1.next = add nuw nsw i64 %iv.1, 1 + %iv.2.next = add nsw i64 %iv.2, -1 + %exitcond.not = icmp eq i64 %iv.1.next, 256 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +define void @non_constant_strides_with_different_directions_2(ptr %A) { +; CHECK-LABEL: 'non_constant_strides_with_different_directions_2' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load i32, ptr %gep.mul.2, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + br label %loop + +loop: + %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ] + %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ] + %iv.mul.2 = shl nuw nsw i64 %iv.2, 1 + %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2 + %l = load i32, ptr %gep.mul.2, align 4 + %add = add nsw i32 %l, 5 + %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1 + store i32 %add, ptr %gep, align 4 + %iv.1.next = add nuw nsw i64 %iv.1, 1 + %iv.2.next = add nsw i64 %iv.2, -1 + %exitcond.not = icmp eq i64 %iv.1.next, 256 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} -- GitLab From bddfbe748ba5fa4363bb343687841f5f389e38f8 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 22 Apr 2024 15:57:59 +0100 Subject: [PATCH 174/357] [VectorCombine] foldShuffleOfShuffles - fold "shuffle (shuffle x, undef), (shuffle y, undef)" -> "shuffle x, y" (#88743) Another step towards cleaning up shuffles that have been split, often across bitcasts between SSE intrinsic. Strip shuffles entirely if we fold to an identity shuffle. --- llvm/include/llvm/IR/PatternMatch.h | 8 + .../Transforms/Vectorize/VectorCombine.cpp | 82 +++++++++ .../AArch64/interleavevectorization.ll | 158 ++++++++---------- .../VectorCombine/AArch64/select-shuffle.ll | 16 +- .../AArch64/shuffletoidentity.ll | 5 +- .../Transforms/VectorCombine/X86/pr67803.ll | 5 +- .../VectorCombine/X86/shuffle-of-shuffles.ll | 14 +- 7 files changed, 167 insertions(+), 121 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 1b418a985454..1fee1901fabb 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -151,6 +151,11 @@ struct undef_match { /// neither undef nor poison, the aggregate is not matched. inline auto m_Undef() { return undef_match(); } +/// Match an arbitrary UndefValue constant. +inline class_match m_UndefValue() { + return class_match(); +} + /// Match an arbitrary poison constant. inline class_match m_Poison() { return class_match(); @@ -777,6 +782,9 @@ m_WithOverflowInst(const WithOverflowInst *&I) { return I; } +/// Match an UndefValue, capturing the value if we match. +inline bind_ty m_UndefValue(UndefValue *&U) { return U; } + /// Match a Constant, capturing the value if we match. inline bind_ty m_Constant(Constant *&C) { return C; } diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index f23b10540338..df761f9b711a 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -113,6 +113,7 @@ private: bool scalarizeLoadExtract(Instruction &I); bool foldShuffleOfBinops(Instruction &I); bool foldShuffleOfCastops(Instruction &I); + bool foldShuffleOfShuffles(Instruction &I); bool foldShuffleFromReductions(Instruction &I); bool foldTruncFromReductions(Instruction &I); bool foldSelectShuffle(Instruction &I, bool FromReduction = false); @@ -1552,6 +1553,86 @@ bool VectorCombine::foldShuffleOfCastops(Instruction &I) { return true; } +/// Try to convert "shuffle (shuffle x, undef), (shuffle y, undef)" +/// into "shuffle x, y". +bool VectorCombine::foldShuffleOfShuffles(Instruction &I) { + Value *V0, *V1; + UndefValue *U0, *U1; + ArrayRef OuterMask, InnerMask0, InnerMask1; + if (!match(&I, m_Shuffle(m_OneUse(m_Shuffle(m_Value(V0), m_UndefValue(U0), + m_Mask(InnerMask0))), + m_OneUse(m_Shuffle(m_Value(V1), m_UndefValue(U1), + m_Mask(InnerMask1))), + m_Mask(OuterMask)))) + return false; + + auto *ShuffleDstTy = dyn_cast(I.getType()); + auto *ShuffleSrcTy = dyn_cast(V0->getType()); + auto *ShuffleImmTy = dyn_cast(I.getOperand(0)->getType()); + if (!ShuffleDstTy || !ShuffleSrcTy || !ShuffleImmTy || + V0->getType() != V1->getType()) + return false; + + unsigned NumSrcElts = ShuffleSrcTy->getNumElements(); + unsigned NumImmElts = ShuffleImmTy->getNumElements(); + + // Bail if either inner masks reference a RHS undef arg. + if ((!isa(U0) && + any_of(InnerMask0, [&](int M) { return M >= (int)NumSrcElts; })) || + (!isa(U1) && + any_of(InnerMask1, [&](int M) { return M >= (int)NumSrcElts; }))) + return false; + + // Merge shuffles - replace index to the RHS poison arg with PoisonMaskElem, + SmallVector NewMask(OuterMask.begin(), OuterMask.end()); + for (int &M : NewMask) { + if (0 <= M && M < (int)NumImmElts) { + M = (InnerMask0[M] >= (int)NumSrcElts) ? PoisonMaskElem : InnerMask0[M]; + } else if (M >= (int)NumImmElts) { + if (InnerMask1[M - NumImmElts] >= (int)NumSrcElts) + M = PoisonMaskElem; + else + M = InnerMask1[M - NumImmElts] + (V0 == V1 ? 0 : NumSrcElts); + } + } + + // Have we folded to an Identity shuffle? + if (ShuffleVectorInst::isIdentityMask(NewMask, NumSrcElts)) { + replaceValue(I, *V0); + return true; + } + + // Try to merge the shuffles if the new shuffle is not costly. + TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; + + InstructionCost OldCost = + TTI.getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, ShuffleSrcTy, + InnerMask0, CostKind) + + TTI.getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, ShuffleSrcTy, + InnerMask1, CostKind) + + TTI.getShuffleCost(TargetTransformInfo::SK_PermuteTwoSrc, ShuffleImmTy, + OuterMask, CostKind, 0, nullptr, std::nullopt, &I); + + InstructionCost NewCost = TTI.getShuffleCost( + TargetTransformInfo::SK_PermuteTwoSrc, ShuffleSrcTy, NewMask, CostKind); + + LLVM_DEBUG(dbgs() << "Found a shuffle feeding two shuffles: " << I + << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost + << "\n"); + if (NewCost > OldCost) + return false; + + // Clear unused sources to poison. + if (none_of(NewMask, [&](int M) { return 0 <= M && M < (int)NumSrcElts; })) + V0 = PoisonValue::get(ShuffleSrcTy); + if (none_of(NewMask, [&](int M) { return (int)NumSrcElts <= M; })) + V1 = PoisonValue::get(ShuffleSrcTy); + + Value *Shuf = Builder.CreateShuffleVector(V0, V1, NewMask); + replaceValue(I, *Shuf); + return true; +} + /// Given a commutative reduction, the order of the input lanes does not alter /// the results. We can use this to remove certain shuffles feeding the /// reduction, removing the need to shuffle at all. @@ -2107,6 +2188,7 @@ bool VectorCombine::run() { case Instruction::ShuffleVector: MadeChange |= foldShuffleOfBinops(I); MadeChange |= foldShuffleOfCastops(I); + MadeChange |= foldShuffleOfShuffles(I); MadeChange |= foldSelectShuffle(I); break; case Instruction::BitCast: diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll index b49c0ad99766..f1d7c0e0c412 100644 --- a/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/interleavevectorization.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -passes='default' -S -o - %s | FileCheck %s +; RUN: opt -passes="default" -S -o - %s | FileCheck %s target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" target triple = "aarch64" @@ -23,22 +23,18 @@ define void @add4(ptr noalias noundef %x, ptr noalias noundef %y, i32 noundef %n ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[WIDE_VEC24:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 ; CHECK-NEXT: [[TMP2:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] ; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 ; CHECK-NEXT: [[TMP6:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP6]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 -; CHECK-NEXT: [[TMP9:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i16> [[TMP9]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP8]] -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP5]], <16 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> [[TMP10]], <16 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP11]], <16 x i16> [[TMP12]], <32 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> [[TMP3]], <16 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP7]], <16 x i16> [[TMP8]], <32 x i32> ; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP13]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP9]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: ret void ; @@ -156,22 +152,18 @@ define void @addsubs(ptr noalias noundef %x, ptr noundef %y, i32 noundef %n) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[WIDE_VEC24:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 ; CHECK-NEXT: [[TMP2:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP6]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 -; CHECK-NEXT: [[TMP9:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i16> [[TMP9]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP8]] -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP5]], <16 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> [[TMP10]], <16 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP11]], <16 x i16> [[TMP12]], <32 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP6:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> [[TMP3]], <16 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP7]], <16 x i16> [[TMP8]], <32 x i32> ; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP13]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP9]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: ret void ; @@ -289,22 +281,18 @@ define void @add2sub2(ptr noalias noundef %x, ptr noundef %y, i32 noundef %n) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[WIDE_VEC24:%.*]] = load <32 x i16>, ptr [[TMP1]], align 2 ; CHECK-NEXT: [[TMP2:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = add <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP4:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 ; CHECK-NEXT: [[TMP6:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP6]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 -; CHECK-NEXT: [[TMP9:%.*]] = sub <32 x i16> [[WIDE_VEC24]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i16> [[TMP9]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP8]] -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP5]], <16 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> [[TMP10]], <16 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP11]], <16 x i16> [[TMP12]], <32 x i32> +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <32 x i16> [[TMP2]], <32 x i16> [[TMP3]], <16 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP7]], <16 x i16> [[TMP8]], <32 x i32> ; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP13]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP9]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: ret void ; @@ -425,25 +413,21 @@ define void @addmul(ptr noalias noundef %x, ptr noundef %y, ptr noundef %z, i32 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[WIDE_VEC36:%.*]] = load <32 x i16>, ptr [[TMP3]], align 2 ; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[TMP2]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP7:%.*]] = add <32 x i16> [[TMP6]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP7]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP10:%.*]] = add <32 x i16> [[TMP9]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <32 x i16> [[TMP10]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 -; CHECK-NEXT: [[TMP13:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP14:%.*]] = add <32 x i16> [[TMP13]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <32 x i16> [[TMP14]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[TMP8]], <16 x i32> -; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <8 x i16> [[TMP11]], <8 x i16> [[TMP15]], <16 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP16]], <16 x i16> [[TMP17]], <32 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP6:%.*]] = add <32 x i16> [[TMP5]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP7:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = add <32 x i16> [[TMP7]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP9:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP10:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP11:%.*]] = add <32 x i16> [[TMP10]], [[WIDE_VEC36]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP9]] +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <32 x i16> [[TMP8]], <32 x i16> [[TMP11]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP12]], <16 x i16> [[TMP13]], <32 x i32> ; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP18]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP14]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: ret void ; @@ -597,25 +581,21 @@ define void @addsubsmul(ptr noalias noundef %x, ptr noundef %y, ptr noundef %z, ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[WIDE_VEC36:%.*]] = load <32 x i16>, ptr [[TMP3]], align 2 ; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[TMP2]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP7:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP6]] -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP7]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP10:%.*]] = add <32 x i16> [[TMP9]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <32 x i16> [[TMP10]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 -; CHECK-NEXT: [[TMP13:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP14:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP13]] -; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <32 x i16> [[TMP14]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[TMP8]], <16 x i32> -; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <8 x i16> [[TMP11]], <8 x i16> [[TMP15]], <16 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP16]], <16 x i16> [[TMP17]], <32 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP6:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = add <32 x i16> [[TMP7]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP9:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP10:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP11:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP10]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP9]] +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <32 x i16> [[TMP8]], <32 x i16> [[TMP11]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP12]], <16 x i16> [[TMP13]], <32 x i32> ; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP18]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP14]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: ret void ; @@ -769,25 +749,21 @@ define void @add2sub2mul(ptr noalias noundef %x, ptr noundef %y, ptr noundef %z, ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[X]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[WIDE_VEC36:%.*]] = load <32 x i16>, ptr [[TMP3]], align 2 ; CHECK-NEXT: [[TMP4:%.*]] = add <32 x i16> [[TMP2]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP7:%.*]] = add <32 x i16> [[TMP6]], [[WIDE_VEC36]] -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i16> [[TMP7]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP10:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP9]] -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <32 x i16> [[TMP10]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 -; CHECK-NEXT: [[TMP13:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] -; CHECK-NEXT: [[TMP14:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP13]] -; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <32 x i16> [[TMP14]], <32 x i16> poison, <8 x i32> -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> [[TMP8]], <16 x i32> -; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <8 x i16> [[TMP11]], <8 x i16> [[TMP15]], <16 x i32> -; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP16]], <16 x i16> [[TMP17]], <32 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP6:%.*]] = add <32 x i16> [[TMP5]], [[WIDE_VEC36]] +; CHECK-NEXT: [[TMP7:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP7]] +; CHECK-NEXT: [[TMP9:%.*]] = or disjoint i64 [[OFFSET_IDX]], 3 +; CHECK-NEXT: [[TMP10:%.*]] = mul <32 x i16> [[WIDE_VEC31]], [[WIDE_VEC]] +; CHECK-NEXT: [[TMP11:%.*]] = sub <32 x i16> [[WIDE_VEC36]], [[TMP10]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr [[INVARIANT_GEP]], i64 [[TMP9]] +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <32 x i16> [[TMP4]], <32 x i16> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <32 x i16> [[TMP8]], <32 x i16> [[TMP11]], <16 x i32> +; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i16> [[TMP12]], <16 x i16> [[TMP13]], <32 x i32> ; CHECK-NEXT: store <32 x i16> [[INTERLEAVED_VEC]], ptr [[GEP]], align 2 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP18]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP14]], label [[FOR_END:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/VectorCombine/AArch64/select-shuffle.ll b/llvm/test/Transforms/VectorCombine/AArch64/select-shuffle.ll index b27c026dbccf..b49f3c9f3eeb 100644 --- a/llvm/test/Transforms/VectorCombine/AArch64/select-shuffle.ll +++ b/llvm/test/Transforms/VectorCombine/AArch64/select-shuffle.ll @@ -741,18 +741,14 @@ define i32 @full_reorder(ptr nocapture noundef readonly %pix1, i32 noundef %i_pi ; CHECK-NEXT: [[TMP10:%.*]] = load <4 x i8>, ptr [[ARRAYIDX3_2]], align 1 ; CHECK-NEXT: [[TMP11:%.*]] = load <4 x i8>, ptr [[ARRAYIDX5_2]], align 1 ; CHECK-NEXT: [[TMP12:%.*]] = load <4 x i8>, ptr [[ADD_PTR_2]], align 1 -; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <4 x i8> [[TMP12]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP14:%.*]] = shufflevector <4 x i8> [[TMP8]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <16 x i8> [[TMP13]], <16 x i8> [[TMP14]], <16 x i32> +; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <4 x i8> [[TMP12]], <4 x i8> [[TMP8]], <16 x i32> ; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <4 x i8> [[TMP4]], <4 x i8> poison, <16 x i32> ; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <16 x i8> [[TMP15]], <16 x i8> [[TMP16]], <16 x i32> ; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> poison, <16 x i32> ; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <16 x i8> [[TMP17]], <16 x i8> [[TMP18]], <16 x i32> ; CHECK-NEXT: [[TMP20:%.*]] = zext <16 x i8> [[TMP19]] to <16 x i32> ; CHECK-NEXT: [[TMP21:%.*]] = load <4 x i8>, ptr [[ADD_PTR64_2]], align 1 -; CHECK-NEXT: [[TMP22:%.*]] = shufflevector <4 x i8> [[TMP21]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <4 x i8> [[TMP9]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <16 x i8> [[TMP22]], <16 x i8> [[TMP23]], <16 x i32> +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <4 x i8> [[TMP21]], <4 x i8> [[TMP9]], <16 x i32> ; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <4 x i8> [[TMP5]], <4 x i8> poison, <16 x i32> ; CHECK-NEXT: [[TMP26:%.*]] = shufflevector <16 x i8> [[TMP24]], <16 x i8> [[TMP25]], <16 x i32> ; CHECK-NEXT: [[TMP27:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <16 x i32> @@ -760,18 +756,14 @@ define i32 @full_reorder(ptr nocapture noundef readonly %pix1, i32 noundef %i_pi ; CHECK-NEXT: [[TMP29:%.*]] = zext <16 x i8> [[TMP28]] to <16 x i32> ; CHECK-NEXT: [[TMP30:%.*]] = sub nsw <16 x i32> [[TMP20]], [[TMP29]] ; CHECK-NEXT: [[TMP31:%.*]] = load <4 x i8>, ptr [[ARRAYIDX3_3]], align 1 -; CHECK-NEXT: [[TMP32:%.*]] = shufflevector <4 x i8> [[TMP31]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP33:%.*]] = shufflevector <4 x i8> [[TMP10]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP34:%.*]] = shufflevector <16 x i8> [[TMP32]], <16 x i8> [[TMP33]], <16 x i32> +; CHECK-NEXT: [[TMP34:%.*]] = shufflevector <4 x i8> [[TMP31]], <4 x i8> [[TMP10]], <16 x i32> ; CHECK-NEXT: [[TMP35:%.*]] = shufflevector <4 x i8> [[TMP6]], <4 x i8> poison, <16 x i32> ; CHECK-NEXT: [[TMP36:%.*]] = shufflevector <16 x i8> [[TMP34]], <16 x i8> [[TMP35]], <16 x i32> ; CHECK-NEXT: [[TMP37:%.*]] = shufflevector <4 x i8> [[TMP2]], <4 x i8> poison, <16 x i32> ; CHECK-NEXT: [[TMP38:%.*]] = shufflevector <16 x i8> [[TMP36]], <16 x i8> [[TMP37]], <16 x i32> ; CHECK-NEXT: [[TMP39:%.*]] = zext <16 x i8> [[TMP38]] to <16 x i32> ; CHECK-NEXT: [[TMP40:%.*]] = load <4 x i8>, ptr [[ARRAYIDX5_3]], align 1 -; CHECK-NEXT: [[TMP41:%.*]] = shufflevector <4 x i8> [[TMP40]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP42:%.*]] = shufflevector <4 x i8> [[TMP11]], <4 x i8> poison, <16 x i32> -; CHECK-NEXT: [[TMP43:%.*]] = shufflevector <16 x i8> [[TMP41]], <16 x i8> [[TMP42]], <16 x i32> +; CHECK-NEXT: [[TMP43:%.*]] = shufflevector <4 x i8> [[TMP40]], <4 x i8> [[TMP11]], <16 x i32> ; CHECK-NEXT: [[TMP44:%.*]] = shufflevector <4 x i8> [[TMP7]], <4 x i8> poison, <16 x i32> ; CHECK-NEXT: [[TMP45:%.*]] = shufflevector <16 x i8> [[TMP43]], <16 x i8> [[TMP44]], <16 x i32> ; CHECK-NEXT: [[TMP46:%.*]] = shufflevector <4 x i8> [[TMP3]], <4 x i8> poison, <16 x i32> diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll index 56b42380a68b..4cc7d5f25328 100644 --- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll +++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll @@ -5,10 +5,7 @@ target triple = "aarch64" define <8 x i8> @trivial(<8 x i8> %a) { ; CHECK-LABEL: @trivial( -; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <4 x i32> -; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> poison, <4 x i32> -; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[AT]], <4 x i8> [[AB]], <8 x i32> -; CHECK-NEXT: ret <8 x i8> [[R]] +; CHECK-NEXT: ret <8 x i8> [[R:%.*]] ; %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> diff --git a/llvm/test/Transforms/VectorCombine/X86/pr67803.ll b/llvm/test/Transforms/VectorCombine/X86/pr67803.ll index 69fd6f6a10e2..0277580d21fc 100644 --- a/llvm/test/Transforms/VectorCombine/X86/pr67803.ll +++ b/llvm/test/Transforms/VectorCombine/X86/pr67803.ll @@ -6,10 +6,7 @@ define <4 x i64> @PR67803(<8 x i32> %x, <8 x i32> %y, <8 x float> %a, <8 x float ; CHECK-LABEL: @PR67803( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <8 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMP_LO:%.*]] = shufflevector <8 x i1> [[CMP]], <8 x i1> poison, <4 x i32> -; CHECK-NEXT: [[CMP_HI:%.*]] = shufflevector <8 x i1> [[CMP]], <8 x i1> poison, <4 x i32> -; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i1> [[CMP_LO]], <4 x i1> [[CMP_HI]], <8 x i32> -; CHECK-NEXT: [[TMP1:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = sext <8 x i1> [[CMP]] to <8 x i32> ; CHECK-NEXT: [[CONCAT:%.*]] = bitcast <8 x i32> [[TMP1]] to <4 x i64> ; CHECK-NEXT: [[MASK:%.*]] = bitcast <4 x i64> [[CONCAT]] to <8 x float> ; CHECK-NEXT: [[SEL:%.*]] = tail call noundef <8 x float> @llvm.x86.avx.blendv.ps.256(<8 x float> [[A:%.*]], <8 x float> [[B:%.*]], <8 x float> [[MASK]]) diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-shuffles.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-shuffles.ll index b5b5bb997c6c..9079a4f693ab 100644 --- a/llvm/test/Transforms/VectorCombine/X86/shuffle-of-shuffles.ll +++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-of-shuffles.ll @@ -2,15 +2,12 @@ ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=sse2 | FileCheck %s ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=avx2 | FileCheck %s -; TODO: fold to identity +; fold to identity define <8 x i32> @concat_extract_subvectors(<8 x i32> %x) { ; CHECK-LABEL: define <8 x i32> @concat_extract_subvectors( ; CHECK-SAME: <8 x i32> [[X:%.*]]) #[[ATTR0:[0-9]+]] { -; CHECK-NEXT: [[LO:%.*]] = shufflevector <8 x i32> [[X]], <8 x i32> poison, <4 x i32> -; CHECK-NEXT: [[HI:%.*]] = shufflevector <8 x i32> [[X]], <8 x i32> poison, <4 x i32> -; CHECK-NEXT: [[CONCAT:%.*]] = shufflevector <4 x i32> [[LO]], <4 x i32> [[HI]], <8 x i32> -; CHECK-NEXT: ret <8 x i32> [[CONCAT]] +; CHECK-NEXT: ret <8 x i32> [[X]] ; %lo = shufflevector <8 x i32> %x, <8 x i32> poison, <4 x i32> %hi = shufflevector <8 x i32> %x, <8 x i32> poison, <4 x i32> @@ -34,15 +31,12 @@ define <8 x i32> @concat_extract_subvectors_undef(<8 x i32> %x) { ret <8 x i32> %concat } -; negative test - shuffle contains poision +; shuffle contains poison define <8 x i32> @concat_extract_subvectors_poison(<8 x i32> %x) { ; CHECK-LABEL: define <8 x i32> @concat_extract_subvectors_poison( ; CHECK-SAME: <8 x i32> [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[LO:%.*]] = shufflevector <8 x i32> [[X]], <8 x i32> poison, <4 x i32> -; CHECK-NEXT: [[HI:%.*]] = shufflevector <8 x i32> [[X]], <8 x i32> poison, <4 x i32> -; CHECK-NEXT: [[CONCAT:%.*]] = shufflevector <4 x i32> [[LO]], <4 x i32> [[HI]], <8 x i32> -; CHECK-NEXT: ret <8 x i32> [[CONCAT]] +; CHECK-NEXT: ret <8 x i32> [[X]] ; %lo = shufflevector <8 x i32> %x, <8 x i32> poison, <4 x i32> %hi = shufflevector <8 x i32> %x, <8 x i32> poison, <4 x i32> -- GitLab From cce4dc7b7a80347c2ef9ad3d55091dbe7adddcb6 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Mon, 22 Apr 2024 11:01:22 -0400 Subject: [PATCH 175/357] [SystemZ][z/OS] Implement llvm.returnaddress for XPLINK (#89440) The implementation follows the ELF implementation. --- .../Target/SystemZ/SystemZFrameLowering.cpp | 20 +++++---- .../lib/Target/SystemZ/SystemZFrameLowering.h | 25 +++++++++-- .../Target/SystemZ/SystemZISelLowering.cpp | 12 +++--- llvm/test/CodeGen/SystemZ/zos-ret-addr.ll | 41 +++++++++++++++++++ 4 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 llvm/test/CodeGen/SystemZ/zos-ret-addr.ll diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index 6ec46bddb5dc..2683470afc5e 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -56,14 +56,17 @@ static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = { SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl, - bool StackReal) - : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal) {} + bool StackReal, unsigned PointerSize) + : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal), + PointerSize(PointerSize) {} std::unique_ptr SystemZFrameLowering::create(const SystemZSubtarget &STI) { + unsigned PtrSz = + STI.getTargetLowering()->getTargetMachine().getPointerSize(0); if (STI.isTargetXPLINK64()) - return std::make_unique(); - return std::make_unique(); + return std::make_unique(PtrSz); + return std::make_unique(PtrSz); } namespace { @@ -272,9 +275,9 @@ void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF, } } -SystemZELFFrameLowering::SystemZELFFrameLowering() +SystemZELFFrameLowering::SystemZELFFrameLowering(unsigned PointerSize) : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0, - Align(8), /* StackRealignable */ false), + Align(8), /* StackRealignable */ false, PointerSize), RegSpillOffsets(0) { // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not @@ -884,9 +887,10 @@ bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const { return HasPackedStackAttr && CallConv; } -SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering() +SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering(unsigned PointerSize) : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(32), 0, - Align(32), /* StackRealignable */ false), + Align(32), /* StackRealignable */ false, + PointerSize), RegSpillOffsets(-1) { // Create a mapping from register number to save slot offset. diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h index 461318192307..c4367b491f99 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h @@ -22,7 +22,7 @@ class SystemZSubtarget; class SystemZFrameLowering : public TargetFrameLowering { public: SystemZFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl, - bool StackReal); + bool StackReal, unsigned PointerSize); static std::unique_ptr create(const SystemZSubtarget &STI); @@ -45,15 +45,24 @@ public: // Return the offset of the backchain. virtual unsigned getBackchainOffset(MachineFunction &MF) const = 0; + // Return the offset of the return address. + virtual int getReturnAddressOffset(MachineFunction &MF) const = 0; + // Get or create the frame index of where the old frame pointer is stored. virtual int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const = 0; + + // Return the size of a pointer (in bytes). + unsigned getPointerSize() const { return PointerSize; } + +private: + unsigned PointerSize; }; class SystemZELFFrameLowering : public SystemZFrameLowering { IndexedMap RegSpillOffsets; public: - SystemZELFFrameLowering(); + SystemZELFFrameLowering(unsigned PointerSize); // Override TargetFrameLowering. bool @@ -97,6 +106,11 @@ public: return usePackedStack(MF) ? SystemZMC::ELFCallFrameSize - 8 : 0; } + // Return the offset of the return address. + int getReturnAddressOffset(MachineFunction &MF) const override { + return (usePackedStack(MF) ? -2 : 14) * getPointerSize(); + } + // Get or create the frame index of where the old frame pointer is stored. int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override; }; @@ -105,7 +119,7 @@ class SystemZXPLINKFrameLowering : public SystemZFrameLowering { IndexedMap RegSpillOffsets; public: - SystemZXPLINKFrameLowering(); + SystemZXPLINKFrameLowering(unsigned PointerSize); bool assignCalleeSavedSpillSlots(MachineFunction &MF, @@ -146,6 +160,11 @@ public: return 0; } + // Return the offset of the return address. + int getReturnAddressOffset(MachineFunction &MF) const override { + return 3 * getPointerSize(); + } + // Get or create the frame index of where the old frame pointer is stored. int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override; }; diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index b3f93e334a9b..48956b571dc3 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -3816,17 +3816,19 @@ SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op, report_fatal_error("Unsupported stack frame traversal count"); SDValue FrameAddr = lowerFRAMEADDR(Op, DAG); - auto *TFL = Subtarget.getFrameLowering(); - int Offset = (TFL->usePackedStack(MF) ? -2 : 14) * - getTargetMachine().getPointerSize(0); + const auto *TFL = Subtarget.getFrameLowering(); + int Offset = TFL->getReturnAddressOffset(MF); SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, FrameAddr, DAG.getConstant(Offset, DL, PtrVT)); return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo()); } - // Return R14D, which has the return address. Mark it an implicit live-in. - Register LinkReg = MF.addLiveIn(SystemZ::R14D, &SystemZ::GR64BitRegClass); + // Return R14D (Elf) / R7D (XPLINK), which has the return address. Mark it an + // implicit live-in. + SystemZCallingConventionRegisters *CCR = Subtarget.getSpecialRegisters(); + Register LinkReg = MF.addLiveIn(CCR->getReturnFunctionAddressRegister(), + &SystemZ::GR64BitRegClass); return DAG.getCopyFromReg(DAG.getEntryNode(), DL, LinkReg, PtrVT); } diff --git a/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll b/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll new file mode 100644 index 000000000000..aea16114d337 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=s390x-ibm-zos | FileCheck %s + +; The current function's return address is in the link register. +define ptr @rt0() norecurse nounwind readnone { +; CHECK-LABEL: rt0: +; CHECK: lgr 3, 7 +; CHECK-NEXT: b 2(7) +entry: + %0 = tail call ptr @llvm.returnaddress(i32 0) + ret ptr %0 +} + +; Check the caller's return address. +define ptr @rtcaller() nounwind "backchain" { +; CHECK-LABEL: rtcaller: +; CHECK: stmg 4, 7, 2048(4) +; CHECK-NEXT: lg 1, 2048(4) +; CHECK-NEXT: lg 3, 24(1) +; CHECK-NEXT: lmg 4, 7, 2048(4) +; CHECK-NEXT: b 2(7) +entry: + %0 = tail call ptr @llvm.returnaddress(i32 1) + ret ptr %0 +} + +; Check the caller's caller's return address. +define ptr @rtcallercaller() nounwind "backchain" { +; CHECK-LABEL: rtcallercaller: +; CHECK: stmg 4, 7, 2048(4) +; CHECK-NEXT: lg 1, 2048(4) +; CHECK-NEXT: lg 1, 0(1) +; CHECK-NEXT: lg 3, 24(1) +; CHECK-NEXT: lmg 4, 7, 2048(4) +; CHECK-NEXT: b 2(7) +entry: + %0 = tail call ptr @llvm.returnaddress(i32 2) + ret ptr %0 +} + +declare ptr @llvm.returnaddress(i32) nounwind readnone -- GitLab From 19a625a0a7798da030e8d2174a5a243aa565f644 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 22 Apr 2024 08:16:03 -0700 Subject: [PATCH 176/357] [SLP][NFC]Add a test with incorrect size of the external user detection. --- .../AArch64/external-use-icmp.ll | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll new file mode 100644 index 000000000000..19ef99e2b840 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll @@ -0,0 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64 -slp-threshold=-20 -slp-vectorize-hor=0 < %s | FileCheck %s + +define i16 @foo(i16 %in1, i16 %in2) { +; CHECK-LABEL: define i16 @foo( +; CHECK-SAME: i16 [[IN1:%.*]], i16 [[IN2:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i16> poison, i16 [[IN1]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i16> [[TMP0]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> poison, i16 [[IN2]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = mul <2 x i16> [[TMP3]], [[TMP1]] +; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i16> [[TMP4]], +; CHECK-NEXT: [[TMP6:%.*]] = zext <2 x i16> [[TMP5]] to <2 x i64> +; CHECK-NEXT: [[TMP7:%.*]] = icmp ne <2 x i64> [[TMP6]], +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x i1> [[TMP7]], i32 1 +; CHECK-NEXT: [[ZEXT3_1:%.*]] = zext i1 [[TMP8]] to i16 +; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i16> [[TMP4]], i32 1 +; CHECK-NEXT: [[TMP10:%.*]] = zext i16 [[TMP9]] to i64 +; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ne i64 [[TMP10]], 196605 +; CHECK-NEXT: [[ZEXT4_1:%.*]] = zext i1 [[CMP2_1]] to i16 +; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i16 [[ZEXT3_1]], [[ZEXT4_1]] +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP7]], i32 0 +; CHECK-NEXT: [[ZEXT3_2:%.*]] = zext i1 [[TMP11]] to i16 +; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i16> [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP13:%.*]] = zext i16 [[TMP12]] to i64 +; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ne i64 [[TMP13]], 196605 +; CHECK-NEXT: [[ZEXT4_2:%.*]] = zext i1 [[CMP2_2]] to i16 +; CHECK-NEXT: [[ADD2:%.*]] = add nuw nsw i16 [[ADD1]], [[ZEXT4_2]] +; CHECK-NEXT: [[ADD3:%.*]] = add nuw nsw i16 [[ADD2]], [[ZEXT3_2]] +; CHECK-NEXT: ret i16 [[ADD3]] +; +entry: + %zext1_1 = zext i16 %in1 to i64 + %zext2_1 = zext i16 %in2 to i64 + %mul1 = mul nuw nsw i64 %zext2_1, %zext1_1 + %and1 = and i64 %mul1, 65535 + %cmp1_1 = icmp ne i64 %and1, 65533 + %zext3_1 = zext i1 %cmp1_1 to i16 + %cmp2_1 = icmp ne i64 %mul1, 196605 + %zext4_1 = zext i1 %cmp2_1 to i16 + %add1 = add nuw nsw i16 %zext3_1, %zext4_1 + %zext1_2 = zext i16 %in1 to i64 + %zext2_2 = zext i16 %in2 to i64 + %mul2 = mul nuw nsw i64 %zext2_2, %zext1_2 + %and2 = and i64 %mul2, 65535 + %cmp1_2 = icmp ne i64 %and2, 65533 + %zext3_2 = zext i1 %cmp1_2 to i16 + %cmp2_2 = icmp ne i64 %mul2, 196605 + %zext4_2 = zext i1 %cmp2_2 to i16 + %add2 = add nuw nsw i16 %add1, %zext4_2 + %add3 = add nuw nsw i16 %add2, %zext3_2 + ret i16 %add3 +} + + -- GitLab From 102a8110943bf18fab923e01610a693587a01945 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 22 Apr 2024 08:23:15 -0700 Subject: [PATCH 177/357] [SLP]Fix a check for multi-users for icmp user. The compiler should not take into account the type of the cmp instruction, otherwise it may treat the size incorrectly and it may lead to incorrect codegen. --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 3 ++- .../SLPVectorizer/AArch64/external-use-icmp.ll | 13 ++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index e70612ae49f7..6636ccbb8c91 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -14530,7 +14530,8 @@ bool BoUpSLP::collectValuesToDemote( return !all_of(V->users(), [=](User *U) { return getTreeEntry(U) || (UserIgnoreList && UserIgnoreList->contains(U)) || - (U->getType()->isSized() && !U->getType()->isScalableTy() && + (!isa(U) && U->getType()->isSized() && + !U->getType()->isScalableTy() && DL->getTypeSizeInBits(U->getType()) <= BitWidth); }) && !IsPotentiallyTruncated(V, BitWidth); })) diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll index 19ef99e2b840..0c6a976b51a1 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll @@ -7,23 +7,22 @@ define i16 @foo(i16 %in1, i16 %in2) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i16> poison, i16 [[IN1]], i32 0 ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i16> [[TMP0]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i64> ; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> poison, i16 [[IN2]], i32 0 ; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = mul <2 x i16> [[TMP3]], [[TMP1]] -; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i16> [[TMP4]], -; CHECK-NEXT: [[TMP6:%.*]] = zext <2 x i16> [[TMP5]] to <2 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i16> [[TMP3]] to <2 x i64> +; CHECK-NEXT: [[TMP9:%.*]] = mul nuw nsw <2 x i64> [[TMP5]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = and <2 x i64> [[TMP9]], ; CHECK-NEXT: [[TMP7:%.*]] = icmp ne <2 x i64> [[TMP6]], ; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x i1> [[TMP7]], i32 1 ; CHECK-NEXT: [[ZEXT3_1:%.*]] = zext i1 [[TMP8]] to i16 -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i16> [[TMP4]], i32 1 -; CHECK-NEXT: [[TMP10:%.*]] = zext i16 [[TMP9]] to i64 +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[TMP9]], i32 1 ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ne i64 [[TMP10]], 196605 ; CHECK-NEXT: [[ZEXT4_1:%.*]] = zext i1 [[CMP2_1]] to i16 ; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i16 [[ZEXT3_1]], [[ZEXT4_1]] ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP7]], i32 0 ; CHECK-NEXT: [[ZEXT3_2:%.*]] = zext i1 [[TMP11]] to i16 -; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i16> [[TMP4]], i32 0 -; CHECK-NEXT: [[TMP13:%.*]] = zext i16 [[TMP12]] to i64 +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i64> [[TMP9]], i32 0 ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ne i64 [[TMP13]], 196605 ; CHECK-NEXT: [[ZEXT4_2:%.*]] = zext i1 [[CMP2_2]] to i16 ; CHECK-NEXT: [[ADD2:%.*]] = add nuw nsw i16 [[ADD1]], [[ZEXT4_2]] -- GitLab From 6bd29d66398d54869670f237c0ffd34ca84b7abe Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 22 Apr 2024 08:40:19 -0700 Subject: [PATCH 178/357] [SLP]Fix PR89614: phis can be reordered, if reuses are not empty. Need to relax assertion and check ReuseShuffleIndices is not empty, if the root phi node has reorder indices. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 2 +- .../X86/phi-reordered-reshuffled.ll | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/phi-reordered-reshuffled.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 6636ccbb8c91..685a5907d94f 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -12229,7 +12229,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { auto *VecTy = FixedVectorType::get(ScalarTy, E->Scalars.size()); switch (ShuffleOrOp) { case Instruction::PHI: { - assert((E->ReorderIndices.empty() || + assert((E->ReorderIndices.empty() || !E->ReuseShuffleIndices.empty() || E != VectorizableTree.front().get() || !E->UserTreeIndices.empty()) && "PHI reordering is free."); diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-reordered-reshuffled.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-reordered-reshuffled.ll new file mode 100644 index 000000000000..e6fe80851a06 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-reordered-reshuffled.ll @@ -0,0 +1,57 @@ +; 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 -mcpu=znver2 < %s | FileCheck %s + +define void @test() { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[TMP2:%.*]], [[BB1]] ] +; CHECK-NEXT: [[TMP0:%.*]] = phi <2 x i32> [ zeroinitializer, [[BB]] ], [ [[TMP3:%.*]], [[BB1]] ] +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[TMP0]], <2 x i32> poison, <32 x i32> +; CHECK-NEXT: [[TMP2]] = call i32 @llvm.vector.reduce.mul.v32i32(<32 x i32> [[TMP1]]) +; CHECK-NEXT: [[TMP3]] = shufflevector <2 x i32> [[TMP0]], <2 x i32> poison, <2 x i32> +; CHECK-NEXT: br label [[BB1]] +; +bb: + br label %bb1 + +bb1: + %phi = phi i32 [ 0, %bb ], [ %mul33, %bb1 ] + %phi2 = phi i32 [ 0, %bb ], [ %phi3, %bb1 ] + %phi3 = phi i32 [ 0, %bb ], [ %phi2, %bb1 ] + %mul = mul i32 %phi2, %phi2 + %mul4 = mul i32 %phi3, %mul + %mul5 = mul i32 %phi2, %mul4 + %mul6 = mul i32 %phi3, %mul5 + %mul7 = mul i32 %phi2, %mul6 + %mul8 = mul i32 %phi3, %mul7 + %mul9 = mul i32 %phi2, %mul8 + %mul10 = mul i32 %phi3, %mul9 + %mul11 = mul i32 %phi2, %mul10 + %mul12 = mul i32 %phi3, %mul11 + %mul13 = mul i32 %phi2, %mul12 + %mul14 = mul i32 %phi3, %mul13 + %mul15 = mul i32 %phi2, %mul14 + %mul16 = mul i32 %phi3, %mul15 + %mul17 = mul i32 %phi2, %mul16 + %mul18 = mul i32 %phi3, %mul17 + %mul19 = mul i32 %phi2, %mul18 + %mul20 = mul i32 %phi3, %mul19 + %mul21 = mul i32 %phi2, %mul20 + %mul22 = mul i32 %phi3, %mul21 + %mul23 = mul i32 %phi2, %mul22 + %mul24 = mul i32 %phi3, %mul23 + %mul25 = mul i32 %phi2, %mul24 + %mul26 = mul i32 %phi3, %mul25 + %mul27 = mul i32 %phi2, %mul26 + %mul28 = mul i32 %phi3, %mul27 + %mul29 = mul i32 %phi2, %mul28 + %mul30 = mul i32 %phi3, %mul29 + %mul31 = mul i32 %phi2, %mul30 + %mul32 = mul i32 %phi3, %mul31 + %mul33 = mul i32 %phi2, %mul32 + br label %bb1 +} + -- GitLab From 5c4b923c727767c9e6ad16324c559a1a92616171 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 22 Apr 2024 11:48:13 -0400 Subject: [PATCH 179/357] Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (#87541, #88311)" (#88731) Reapplies #87541 and #88311 (again) addressing the bug which caused expressions naming overload sets to be incorrectly rebuilt, as well as the bug which caused base class members to always be treated as overload sets. The primary change since #88311 is `UnresolvedLookupExpr::Create` is called directly in `BuildPossibleImplicitMemberExpr` with `KnownDependent` as `true` (which causes the expression type to be set to `ASTContext::DependentTy`). This ensures that any further semantic analysis involving the type of the potentially implicit class member access expression is deferred until instantiation. --- clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/AST/ExprCXX.h | 9 +- clang/include/clang/AST/Stmt.h | 5 - clang/include/clang/Sema/Sema.h | 13 +- clang/lib/AST/ASTImporter.cpp | 4 +- clang/lib/AST/ExprCXX.cpp | 28 +- clang/lib/Sema/SemaCoroutine.cpp | 7 +- clang/lib/Sema/SemaDecl.cpp | 4 +- clang/lib/Sema/SemaDeclCXX.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 33 +- clang/lib/Sema/SemaExprCXX.cpp | 61 +-- clang/lib/Sema/SemaExprMember.cpp | 72 ++- clang/lib/Sema/SemaOpenMP.cpp | 4 +- clang/lib/Sema/SemaOverload.cpp | 4 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 + clang/lib/Sema/TreeTransform.h | 84 ++-- clang/lib/Serialization/ASTReaderStmt.cpp | 1 - clang/lib/Serialization/ASTWriterStmt.cpp | 1 - .../SemaTemplate/instantiate-using-decl.cpp | 2 +- ...ms-function-specialization-class-scope.cpp | 455 +++++++++++++++++- 20 files changed, 646 insertions(+), 153 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c44f238e3384..db5830a63715 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -538,6 +538,8 @@ Bug Fixes to C++ Support - Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). - Fixed a bug that prevented member function templates of class templates declared with a deduced return type from being explicitly specialized for a given implicit instantiation of the class template. +- Fixed a crash when ``this`` is used in a dependent class scope function template specialization + that instantiates to a static member function. - Fix crash when inheriting from a cv-qualified type. Fixes #GH35603 - Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790). diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index d28e5c3a78ee..a915745d2d73 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3198,7 +3198,6 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, - bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent); @@ -3218,8 +3217,9 @@ public: static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); + const DeclarationNameInfo &NameInfo, bool RequiresADL, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3240,9 +3240,6 @@ public: /// argument-dependent lookup. bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; } - /// True if this lookup is overloaded. - bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; } - /// Gets the 'naming class' (in the sense of C++0x /// [class.access.base]p5) of the lookup. This is the scope /// that was looked in to find these results. diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 1b9c92310477..9cd7a364cd3f 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1067,11 +1067,6 @@ protected: /// argument-dependent lookup if this is the operand of a function call. LLVM_PREFERRED_TYPE(bool) unsigned RequiresADL : 1; - - /// True if these lookup results are overloaded. This is pretty trivially - /// rederivable if we urgently need to kill this field. - LLVM_PREFERRED_TYPE(bool) - unsigned Overloaded : 1; }; static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4, "UnresolvedLookupExprBitfields must be <= than 4 bytes to" diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ffc58c681cdc..64607b91acbf 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6527,7 +6527,10 @@ public: SourceLocation RParenLoc); //// ActOnCXXThis - Parse 'this' pointer. - ExprResult ActOnCXXThis(SourceLocation loc); + ExprResult ActOnCXXThis(SourceLocation Loc); + + /// Check whether the type of 'this' is valid in the current context. + bool CheckCXXThisType(SourceLocation Loc, QualType Type); /// Build a CXXThisExpr and mark it referenced in the current context. Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); @@ -6949,10 +6952,14 @@ private: ///@{ public: + /// Check whether an expression might be an implicit class member access. + bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R, + bool IsAddressOfOperand); + ExprResult BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE = nullptr); + const TemplateArgumentListInfo *TemplateArgs, const Scope *S); + ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index f8180047f686..60f213322b34 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8574,8 +8574,8 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, - ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(), - ToDecls.end()); + ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), + /*KnownDependent=*/E->isTypeDependent()); } ExpectedStmt diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index a58196318843..7e9343271ac3 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -353,7 +353,7 @@ SourceLocation CXXPseudoDestructorExpr::getEndLoc() const { UnresolvedLookupExpr::UnresolvedLookupExpr( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, + const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, @@ -361,7 +361,6 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( KnownDependent, false, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; - UnresolvedLookupExprBits.Overloaded = Overloaded; } UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty, @@ -373,15 +372,16 @@ UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty, UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { + bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent) { unsigned NumResults = End - Begin; unsigned Size = totalSizeToAlloc(NumResults, 0, 0); void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, - SourceLocation(), NameInfo, RequiresADL, - Overloaded, nullptr, Begin, End, false); + return new (Mem) UnresolvedLookupExpr( + Context, NamingClass, QualifierLoc, + /*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL, + /*TemplateArgs=*/nullptr, Begin, End, KnownDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::Create( @@ -390,16 +390,16 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent) { - assert(Args || TemplateKWLoc.isValid()); unsigned NumResults = End - Begin; + bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid(); unsigned NumTemplateArgs = Args ? Args->size() : 0; - unsigned Size = - totalSizeToAlloc(NumResults, 1, NumTemplateArgs); + unsigned Size = totalSizeToAlloc( + NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr( - Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL, - /*Overloaded=*/true, Args, Begin, End, KnownDependent); + return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, + TemplateKWLoc, NameInfo, RequiresADL, + Args, Begin, End, KnownDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty( diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 736632857efc..81334c817b2a 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -817,13 +817,10 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) { assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); const auto &Functions = Operators.asUnresolvedSet(); - bool IsOverloaded = - Functions.size() > 1 || - (Functions.size() == 1 && isa(*Functions.begin())); Expr *CoawaitOp = UnresolvedLookupExpr::Create( Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), - DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded, - Functions.begin(), Functions.end()); + DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(), + Functions.end(), /*KnownDependent=*/false); assert(CoawaitOp); return CoawaitOp; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5fed554d9e25..35eac93e324d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1240,8 +1240,8 @@ Corrected: Result.suppressDiagnostics(); return NameClassification::OverloadSet(UnresolvedLookupExpr::Create( Context, Result.getNamingClass(), SS.getWithLocInContext(Context), - Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(), - Result.begin(), Result.end())); + Result.getLookupNameInfo(), ADL, Result.begin(), Result.end(), + /*KnownDependent=*/false)); } ExprResult diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2ef8a15d5238..abdbc9d8830c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1302,7 +1302,7 @@ static bool checkTupleLikeDecomposition(Sema &S, // in the associated namespaces. Expr *Get = UnresolvedLookupExpr::Create( S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), - DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/ true, &Args, + DeclarationNameInfo(GetDN, Loc), /*RequiresADL=*/true, &Args, UnresolvedSetIterator(), UnresolvedSetIterator(), /*KnownDependent=*/false); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2c444d3f8dc4..092da4a75dc3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2918,26 +2918,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. - if (getLangOpts().CPlusPlus && !R.empty() && - (*R.begin())->isCXXClassMember()) { - bool MightBeImplicitMember; - if (!IsAddressOfOperand) - MightBeImplicitMember = true; - else if (!SS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa(R.getFoundDecl()) || - isa(R.getFoundDecl()) || - isa(R.getFoundDecl()); - - if (MightBeImplicitMember) - return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, - R, TemplateArgs, S); - } + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + S); if (TemplateArgs || TemplateKWLoc.isValid()) { @@ -3471,12 +3454,10 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // we've picked a target. R.suppressDiagnostics(); - UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - SS.getWithLocInContext(Context), - R.getLookupNameInfo(), - NeedsADL, R.isOverloadedResult(), - R.begin(), R.end()); + UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create( + Context, R.getNamingClass(), SS.getWithLocInContext(Context), + R.getLookupNameInfo(), NeedsADL, R.begin(), R.end(), + /*KnownDependent=*/false); return ULE; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7582cbd75fec..779a41620033 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1416,26 +1416,42 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, } ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { - /// C++ 9.3.2: In the body of a non-static member function, the keyword this - /// is a non-lvalue expression whose value is the address of the object for - /// which the function is called. + // C++20 [expr.prim.this]p1: + // The keyword this names a pointer to the object for which an + // implicit object member function is invoked or a non-static + // data member's initializer is evaluated. QualType ThisTy = getCurrentThisType(); - if (ThisTy.isNull()) { - DeclContext *DC = getFunctionLevelDeclContext(); + if (CheckCXXThisType(Loc, ThisTy)) + return ExprError(); - if (const auto *Method = dyn_cast(DC); - Method && Method->isExplicitObjectMemberFunction()) { - return Diag(Loc, diag::err_invalid_this_use) << 1; - } + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); +} - if (isLambdaCallWithExplicitObjectParameter(CurContext)) - return Diag(Loc, diag::err_invalid_this_use) << 1; +bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) { + if (!Type.isNull()) + return false; - return Diag(Loc, diag::err_invalid_this_use) << 0; + // C++20 [expr.prim.this]p3: + // If a declaration declares a member function or member function template + // of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" wherever X is the current class between + // the optional cv-qualifier-seq and the end of the function-definition, + // member-declarator, or declarator. It shall not appear within the + // declaration of either a static member function or an explicit object + // member function of the current class (although its type and value + // category are defined within such member functions as they are within + // an implicit object member function). + DeclContext *DC = getFunctionLevelDeclContext(); + if (const auto *Method = dyn_cast(DC); + Method && Method->isExplicitObjectMemberFunction()) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else if (isLambdaCallWithExplicitObjectParameter(CurContext)) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else { + Diag(Loc, diag::err_invalid_this_use) << 0; } - - return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); + return true; } Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, @@ -8644,21 +8660,8 @@ static ExprResult attemptRecovery(Sema &SemaRef, // Detect and handle the case where the decl might be an implicit // member. - bool MightBeImplicitMember; - if (!Consumer.isAddressOfOperand()) - MightBeImplicitMember = true; - else if (!NewSS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa(ND) || - isa(ND) || - isa(ND); - - if (MightBeImplicitMember) + if (SemaRef.isPotentialImplicitMemberAccess( + NewSS, R, Consumer.isAddressOfOperand())) return SemaRef.BuildPossibleImplicitMemberExpr( NewSS, /*TemplateKWLoc*/ SourceLocation(), R, /*TemplateArgs*/ nullptr, /*S*/ nullptr); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index c79128bc8f39..6e30716b9ae4 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -62,6 +62,10 @@ enum IMAKind { /// The reference is a contextually-permitted abstract member reference. IMA_Abstract, + /// Whether the context is static is dependent on the enclosing template (i.e. + /// in a dependent class scope explicit specialization). + IMA_Dependent, + /// The reference may be to an unresolved using declaration and the /// context is not an instance method. IMA_Unresolved_StaticOrExplicitContext, @@ -92,14 +96,25 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); - bool isStaticOrExplicitContext = - SemaRef.CXXThisTypeOverride.isNull() && - (!isa(DC) || cast(DC)->isStatic() || - cast(DC)->isExplicitObjectMemberFunction()); + bool couldInstantiateToStatic = false; + bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull(); - if (R.isUnresolvableResult()) + if (auto *MD = dyn_cast(DC)) { + if (MD->isImplicitObjectMemberFunction()) { + isStaticOrExplicitContext = false; + // A dependent class scope function template explicit specialization + // that is neither declared 'static' nor with an explicit object + // parameter could instantiate to a static or non-static member function. + couldInstantiateToStatic = MD->getDependentSpecializationInfo(); + } + } + + if (R.isUnresolvableResult()) { + if (couldInstantiateToStatic) + return IMA_Dependent; return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext : IMA_Unresolved; + } // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; @@ -124,6 +139,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; + if (couldInstantiateToStatic) + return IMA_Dependent; + // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static // member function of a class can only be used: @@ -264,21 +282,37 @@ static void diagnoseInstanceReference(Sema &SemaRef, } } +bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, + LookupResult &R, + bool IsAddressOfOperand) { + if (!getLangOpts().CPlusPlus) + return false; + else if (R.empty() || !R.begin()->isCXXClassMember()) + return false; + else if (!IsAddressOfOperand) + return true; + else if (!SS.isEmpty()) + return false; + else if (R.isOverloadedResult()) + return false; + else if (R.isUnresolvableResult()) + return true; + else + return isa(R.getFoundDecl()); +} + /// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE) { - switch (ClassifyImplicitMemberAccess(*this, R)) { + const TemplateArgumentListInfo *TemplateArgs, const Scope *S) { + switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) { case IMA_Instance: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); - case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false, - S); - + return BuildImplicitMemberExpr( + SS, TemplateKWLoc, R, TemplateArgs, + /*IsKnownInstance=*/Classification == IMA_Instance, S); case IMA_Field_Uneval_Context: Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) << R.getLookupNameInfo().getName(); @@ -288,8 +322,16 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr( case IMA_Mixed_StaticOrExplicitContext: case IMA_Unresolved_StaticOrExplicitContext: if (TemplateArgs || TemplateKWLoc.isValid()) - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); - return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false, + TemplateArgs); + return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false, + /*AcceptInvalidDecl=*/false); + case IMA_Dependent: + R.suppressDiagnostics(); + return UnresolvedLookupExpr::Create( + Context, R.getNamingClass(), SS.getWithLocInContext(Context), + TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false, + TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true); case IMA_Error_StaticOrExplicitContext: case IMA_Error_Unrelated: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 3e9f6cba2507..5ba09926acf2 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -19354,7 +19354,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, return UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, - /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end()); + /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false); } // Lookup inside the classes. // C++ [over.match.oper]p3: @@ -22220,7 +22220,7 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, return UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId, - /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end()); + /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false); } SourceLocation Loc = MapperId.getLoc(); // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 48d6264029e9..a2763e331357 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14273,8 +14273,8 @@ ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, const UnresolvedSetImpl &Fns, bool PerformADL) { return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI, - PerformADL, IsOverloaded(Fns), - Fns.begin(), Fns.end()); + PerformADL, Fns.begin(), Fns.end(), + /*KnownDependent=*/false); } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index caa07abb61fe..787a485e0b2f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5101,6 +5101,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + Qualifiers ThisTypeQuals; + CXXRecordDecl *ThisContext = nullptr; + if (CXXMethodDecl *Method = dyn_cast(Function)) { + ThisContext = Method->getParent(); + ThisTypeQuals = Method->getMethodQualifiers(); + } + CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals); + // Introduce a new scope where local variable instantiations will be // recorded, unless we're actually a member function within a local // class, in which case we need to merge our results with the parent diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 180574f1cab8..13f7e9b3fbe3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -796,6 +796,9 @@ public: ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI); + ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, + bool IsAddressOfOperand); + StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S); // FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous @@ -3320,12 +3323,13 @@ public: /// Build a new C++ "this" expression. /// - /// By default, builds a new "this" expression without performing any - /// semantic analysis. Subclasses may override this routine to provide - /// different behavior. + /// By default, performs semantic analysis to build a new "this" expression. + /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { + if (getSema().CheckCXXThisType(ThisLoc, ThisType)) + return ExprError(); return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit); } @@ -10427,12 +10431,11 @@ TreeTransform::TransformOMPReductionClause(OMPReductionClause *C) { cast(getDerived().TransformDecl(E->getExprLoc(), D)); Decls.addDecl(InstD, InstD->getAccess()); } - UnresolvedReductions.push_back( - UnresolvedLookupExpr::Create( + UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, - ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), - NameInfo, /*ADL=*/true, ULE->isOverloaded(), - Decls.begin(), Decls.end())); + ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, + /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10478,7 +10481,8 @@ OMPClause *TreeTransform::TransformOMPTaskReductionClause( UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, - /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end())); + /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10523,7 +10527,8 @@ TreeTransform::TransformOMPInReductionClause(OMPInReductionClause *C) { UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, - /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end())); + /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10704,8 +10709,8 @@ bool transformOMPMappableExprListClause( UnresolvedMappers.push_back(UnresolvedLookupExpr::Create( TT.getSema().Context, /*NamingClass=*/nullptr, MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context), - MapperIdInfo, /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), - Decls.end())); + MapperIdInfo, /*ADL=*/true, Decls.begin(), Decls.end(), + /*KnownDependent=*/false)); } else { UnresolvedMappers.push_back(nullptr); } @@ -11465,7 +11470,11 @@ template ExprResult TreeTransform::TransformAddressOfOperand(Expr *E) { if (DependentScopeDeclRefExpr *DRE = dyn_cast(E)) - return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr); + return getDerived().TransformDependentScopeDeclRefExpr( + DRE, /*IsAddressOfOperand=*/true, nullptr); + else if (UnresolvedLookupExpr *ULE = dyn_cast(E)) + return getDerived().TransformUnresolvedLookupExpr( + ULE, /*IsAddressOfOperand=*/true); else return getDerived().TransformExpr(E); } @@ -13172,10 +13181,16 @@ bool TreeTransform::TransformOverloadExprDecls(OverloadExpr *Old, return false; } -template +template +ExprResult TreeTransform::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old) { + return TransformUnresolvedLookupExpr(Old, /*IsAddressOfOperand=*/false); +} + +template ExprResult -TreeTransform::TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *Old) { +TreeTransform::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, + bool IsAddressOfOperand) { LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), Sema::LookupOrdinaryName); @@ -13207,26 +13222,8 @@ TreeTransform::TransformUnresolvedLookupExpr( R.setNamingClass(NamingClass); } + // Rebuild the template arguments, if any. SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); - - // If we have neither explicit template arguments, nor the template keyword, - // it's a normal declaration name or member reference. - if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) { - NamedDecl *D = R.getAsSingle(); - // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an - // instance member. In other contexts, BuildPossibleImplicitMemberExpr will - // give a good diagnostic. - if (D && D->isCXXInstanceMember()) { - return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, - /*TemplateArgs=*/nullptr, - /*Scope=*/nullptr); - } - - return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); - } - - // If we have template arguments, rebuild them, then rebuild the - // templateid expression. TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); if (Old->hasExplicitTemplateArgs() && getDerived().TransformTemplateArguments(Old->getTemplateArgs(), @@ -13236,6 +13233,23 @@ TreeTransform::TransformUnresolvedLookupExpr( return ExprError(); } + // An UnresolvedLookupExpr can refer to a class member. This occurs e.g. when + // a non-static data member is named in an unevaluated operand, or when + // a member is named in a dependent class scope function template explicit + // specialization that is neither declared static nor with an explicit object + // parameter. + if (SemaRef.isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return SemaRef.BuildPossibleImplicitMemberExpr( + SS, TemplateKWLoc, R, + Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr, + /*S=*/nullptr); + + // If we have neither explicit template arguments, nor the template keyword, + // it's a normal declaration name or member reference. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + + // If we have template arguments, then rebuild the template-id expression. return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R, Old->requiresADL(), &TransArgs); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index ca0460800898..baded0fe1983 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2096,7 +2096,6 @@ void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); E->UnresolvedLookupExprBits.RequiresADL = CurrentUnpackingBits->getNextBit(); - E->UnresolvedLookupExprBits.Overloaded = CurrentUnpackingBits->getNextBit(); E->NamingClass = readDeclAs(); } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index a736a7b0ef72..cd5f733baf76 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2082,7 +2082,6 @@ void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); CurrentPackingBits.addBit(E->requiresADL()); - CurrentPackingBits.addBit(E->isOverloaded()); Record.AddDeclRef(E->getNamingClass()); Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; } diff --git a/clang/test/SemaTemplate/instantiate-using-decl.cpp b/clang/test/SemaTemplate/instantiate-using-decl.cpp index 0bbb3ca9c88c..28d837643851 100644 --- a/clang/test/SemaTemplate/instantiate-using-decl.cpp +++ b/clang/test/SemaTemplate/instantiate-using-decl.cpp @@ -121,7 +121,7 @@ template struct Derived : Base { (void)&field; // expected-error@+1 {{call to non-static member function without an object argument}} (void)method; - // expected-error@+1 {{call to non-static member function without an object argument}} + // expected-error@+1 {{must explicitly qualify name of member function when taking its address}} (void)&method; // expected-error@+1 {{call to non-static member function without an object argument}} method(); diff --git a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp index dcab9bfaeabc..c49d2cb2422f 100644 --- a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp +++ b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -1,7 +1,6 @@ -// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s -// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -Wno-unused-value -verify %s +// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -Wno-unused-value -verify %s -// expected-no-diagnostics class A { public: template A(U p) {} @@ -76,3 +75,453 @@ struct S { int f<0>(int); }; } + +namespace UsesThis { + template + struct A { + int x; + + static inline int y; + + template + static void f(); + + template + void g(); + + template + static auto h() -> A*; + + void i(); + + static void j(); + + template<> + void f() { + this->x; // expected-error {{invalid use of 'this' outside of a non-static member function}} + x; // expected-error {{invalid use of member 'x' in static member function}} + A::x; // expected-error {{invalid use of member 'x' in static member function}} + +x; // expected-error {{invalid use of member 'x' in static member function}} + +A::x; // expected-error {{invalid use of member 'x' in static member function}} + &x; // expected-error {{invalid use of member 'x' in static member function}} + &A::x; + this->y; // expected-error {{invalid use of 'this' outside of a non-static member function}} + y; + A::y; + +y; + +A::y; + &y; + &A::y; + f(); + f(); + g(); // expected-error {{call to non-static member function without an object argument}} + g(); // expected-error {{call to non-static member function without an object argument}} + i(); // expected-error {{call to non-static member function without an object argument}} + j(); + &i; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &j; + &A::i; + &A::j; + } + + template<> + void g() { + this->x; + x; + A::x; + +x; + +A::x; + &x; + &A::x; + this->y; + y; + A::y; + +y; + +A::y; + &y; + &A::y; + f(); + f(); + g(); + g(); + i(); + j(); + &i; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &j; + &A::i; + &A::j; + } + + template<> + auto h() -> decltype(this); // expected-error {{'this' cannot be used in a static member function declaration}} + }; + + template struct A; // expected-note 3{{in instantiation of}} + + template + struct Foo { + template + int bar(X x) { + return 0; + } + + template <> + int bar(int x) { + return bar(5.0); // ok + } + }; + + void call() { + Foo f; + f.bar(1); + } + + struct B { + int x0; + static inline int y0; + + int f0(int); + static int g0(int); + + int x2; + static inline int y2; + + int f2(int); + static int g2(int); + }; + + template + struct D : B { + int x1; + static inline int y1; + + int f1(int); + static int g1(int); + + using B::x2; + using B::y2; + using B::f2; + using B::g2; + + template + void non_static_spec(U); + + template + static void static_spec(U); + + template<> + void non_static_spec(int z) { + ++z; + ++x0; + ++x1; + ++x2; + ++y0; + ++y1; + ++y2; + + &z; + &x0; + &x1; + &x2; + &y0; + &y1; + &y2; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &f2; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + &g2; + + &B::x0; + &D::x1; + &B::x2; + &B::y0; + &D::y1; + &B::y2; + &B::f0; + &D::f1; + &B::f2; + &B::g0; + &D::g1; + &B::g2; + + f0(0); + f0(z); + f0(x0); + f0(x1); + f0(x2); + f0(y0); + f0(y1); + f0(y2); + g0(0); + g0(z); + g0(x0); + g0(x1); + g0(x2); + g0(y0); + g0(y1); + g0(y2); + + f1(0); + f1(z); + f1(x0); + f1(x1); + f1(x2); + f1(y0); + f1(y1); + f1(y2); + g1(0); + g1(z); + g1(x0); + g1(x1); + g1(x2); + g1(y0); + g1(y1); + g1(y2); + + f2(0); + f2(z); + f2(x0); + f2(x1); + f2(x2); + f2(y0); + f2(y1); + f2(y2); + g2(0); + g2(z); + g2(x0); + g2(x1); + g2(x2); + g2(y0); + g2(y1); + g2(y2); + } + + template<> + void static_spec(int z) { + ++z; + ++x0; // expected-error {{invalid use of member 'x0' in static member function}} + ++x1; // expected-error {{invalid use of member 'x1' in static member function}} + ++x2; // expected-error {{invalid use of member 'x2' in static member function}} + ++y0; + ++y1; + ++y2; + + &z; + &x0; // expected-error {{invalid use of member 'x0' in static member function}} + &x1; // expected-error {{invalid use of member 'x1' in static member function}} + &x2; // expected-error {{invalid use of member 'x2' in static member function}} + &y0; + &y1; + &y2; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &f2; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + &g2; + + &B::x0; + &D::x1; + &B::x2; + &B::y0; + &D::y1; + &B::y2; + &B::f0; + &D::f1; + &B::f2; + &B::g0; + &D::g1; + &B::g2; + + f0(0); // expected-error {{call to non-static member function without an object argument}} + f0(z); // expected-error {{call to non-static member function without an object argument}} + f0(x0); // expected-error {{call to non-static member function without an object argument}} + f0(x1); // expected-error {{call to non-static member function without an object argument}} + f0(x2); // expected-error {{call to non-static member function without an object argument}} + f0(y0); // expected-error {{call to non-static member function without an object argument}} + f0(y1); // expected-error {{call to non-static member function without an object argument}} + f0(y2); // expected-error {{call to non-static member function without an object argument}} + g0(0); + g0(z); + g0(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g0(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g0(x2); // expected-error {{invalid use of member 'x2' in static member function}} + g0(y0); + g0(y1); + g0(y2); + + f1(0); // expected-error {{call to non-static member function without an object argument}} + f1(z); // expected-error {{call to non-static member function without an object argument}} + f1(x0); // expected-error {{call to non-static member function without an object argument}} + f1(x1); // expected-error {{call to non-static member function without an object argument}} + f1(x2); // expected-error {{call to non-static member function without an object argument}} + f1(y0); // expected-error {{call to non-static member function without an object argument}} + f1(y1); // expected-error {{call to non-static member function without an object argument}} + f1(y2); // expected-error {{call to non-static member function without an object argument}} + g1(0); + g1(z); + g1(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g1(x2); // expected-error {{invalid use of member 'x2' in static member function}} + g1(y0); + g1(y1); + g1(y2); + + f2(0); // expected-error {{call to non-static member function without an object argument}} + f2(z); // expected-error {{call to non-static member function without an object argument}} + f2(x0); // expected-error {{call to non-static member function without an object argument}} + f2(x1); // expected-error {{call to non-static member function without an object argument}} + f2(x2); // expected-error {{call to non-static member function without an object argument}} + f2(y0); // expected-error {{call to non-static member function without an object argument}} + f2(y1); // expected-error {{call to non-static member function without an object argument}} + f2(y2); // expected-error {{call to non-static member function without an object argument}} + g2(0); + g2(z); + g2(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g2(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g2(x2); // expected-error {{invalid use of member 'x2' in static member function}} + g2(y0); + g2(y1); + g2(y2); + } + }; + + template struct D; // expected-note 2{{in instantiation of}} + + template + struct E : T { + int x1; + static inline int y1; + + int f1(int); + static int g1(int); + + using T::x0; + using T::y0; + using T::f0; + using T::g0; + + template + void non_static_spec(U); + + template + static void static_spec(U); + + template<> + void non_static_spec(int z) { + ++z; + ++x0; + ++x1; + ++y0; + ++y1; + + &z; + &x0; + &x1; + &y0; + &y1; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + + &T::x0; + &E::x1; + &T::y0; + &E::y1; + &T::f0; + &E::f1; + &T::g0; + &E::g1; + + f0(0); + f0(z); + f0(x0); + f0(x1); + f0(y0); + f0(y1); + g0(0); + g0(z); + g0(x0); + g0(x1); + g0(y0); + g0(y1); + + f1(0); + f1(z); + f1(x0); + f1(x1); + f1(y0); + f1(y1); + g1(0); + g1(z); + g1(x0); + g1(x1); + g1(y0); + g1(y1); + } + + template<> + void static_spec(int z) { + ++z; + ++x0; // expected-error {{invalid use of member 'x0' in static member function}} + ++x1; // expected-error {{invalid use of member 'x1' in static member function}} + ++y0; + ++y1; + + &z; + &x0; // expected-error {{invalid use of member 'x0' in static member function}} + &x1; // expected-error {{invalid use of member 'x1' in static member function}} + &y0; + &y1; + + &f0; // expected-error {{must explicitly qualify name of member function when taking its address}} + &f1; // expected-error 2{{must explicitly qualify name of member function when taking its address}} + &g0; + &g1; + + &T::x0; + &E::x1; + &T::y0; + &E::y1; + &T::f0; + &E::f1; + &T::g0; + &E::g1; + + f0(0); // expected-error {{call to non-static member function without an object argument}} + f0(z); // expected-error {{call to non-static member function without an object argument}} + f0(x0); // expected-error {{call to non-static member function without an object argument}} + f0(x1); // expected-error {{call to non-static member function without an object argument}} + f0(y0); // expected-error {{call to non-static member function without an object argument}} + f0(y1); // expected-error {{call to non-static member function without an object argument}} + g0(0); + g0(z); + g0(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g0(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g0(y0); + g0(y1); + + f1(0); // expected-error {{call to non-static member function without an object argument}} + f1(z); // expected-error {{call to non-static member function without an object argument}} + f1(x0); // expected-error {{call to non-static member function without an object argument}} + f1(x1); // expected-error {{call to non-static member function without an object argument}} + f1(y0); // expected-error {{call to non-static member function without an object argument}} + f1(y1); // expected-error {{call to non-static member function without an object argument}} + g1(0); + g1(z); + g1(x0); // expected-error {{invalid use of member 'x0' in static member function}} + g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} + g1(y0); + g1(y1); + } + }; + + template struct E; // expected-note 2{{in instantiation of}} + +} -- GitLab From dc20a0ea1fd04a2ef95eb5c73e9f88357fc5f694 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 22 Apr 2024 08:57:25 -0700 Subject: [PATCH 180/357] [OpenACC] Implement 'num_gangs' sema for compute constructs (#89460) num_gangs takes an 'int-expr-list', for 'parallel', and an 'int-expr' for 'kernels'. This patch changes the parsing to always parse it as an 'int-expr-list', then correct the expression count during Sema. It also implements the rest of the semantic analysis changes for this clause. --- clang/include/clang/AST/OpenACCClause.h | 87 ++++++++-- .../clang/Basic/DiagnosticSemaKinds.td | 5 + clang/include/clang/Basic/OpenACCClauses.def | 1 + clang/include/clang/Parse/Parser.h | 16 +- clang/include/clang/Sema/SemaOpenACC.h | 16 +- clang/lib/AST/OpenACCClause.cpp | 16 ++ clang/lib/AST/StmtProfile.cpp | 6 + clang/lib/AST/TextNodeDumper.cpp | 1 + clang/lib/Parse/ParseOpenACC.cpp | 87 ++++++++-- clang/lib/Sema/SemaOpenACC.cpp | 35 ++++ clang/lib/Sema/TreeTransform.h | 26 +++ clang/lib/Serialization/ASTReader.cpp | 10 +- clang/lib/Serialization/ASTWriter.cpp | 9 +- clang/test/ParserOpenACC/parse-clauses.c | 4 - .../compute-construct-intexpr-clause-ast.cpp | 79 +++++++++ .../compute-construct-num_gangs-clause.c | 54 ++++++ .../compute-construct-num_gangs-clause.cpp | 160 ++++++++++++++++++ clang/tools/libclang/CIndex.cpp | 4 + 18 files changed, 572 insertions(+), 44 deletions(-) create mode 100644 clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c create mode 100644 clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 8b6d3221aa06..277a351c49fc 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -156,33 +156,88 @@ public: Expr *ConditionExpr, SourceLocation EndLoc); }; -/// Represents oen of a handful of classes that have a single integer +/// Represents a clause that has one or more IntExprs. It does not own the +/// IntExprs, but provides 'children' and other accessors. +class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams { + MutableArrayRef IntExprs; + +protected: + OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {} + + /// Used only for initialization, the leaf class can initialize this to + /// trailing storage. + void setIntExprs(MutableArrayRef NewIntExprs) { + assert(IntExprs.empty() && "Cannot change IntExprs list"); + IntExprs = NewIntExprs; + } + + /// Gets the entire list of integer expressions, but leave it to the + /// individual clauses to expose this how they'd like. + llvm::ArrayRef getIntExprs() const { return IntExprs; } + +public: + child_range children() { + return child_range(reinterpret_cast(IntExprs.begin()), + reinterpret_cast(IntExprs.end())); + } + + const_child_range children() const { + child_range Children = + const_cast(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } +}; + +class OpenACCNumGangsClause final + : public OpenACCClauseWithIntExprs, + public llvm::TrailingObjects { + + OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef IntExprs, SourceLocation EndLoc) + : OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc, + LParenLoc, EndLoc) { + std::uninitialized_copy(IntExprs.begin(), IntExprs.end(), + getTrailingObjects()); + setIntExprs(MutableArrayRef(getTrailingObjects(), IntExprs.size())); + } + +public: + static OpenACCNumGangsClause * + Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, + ArrayRef IntExprs, SourceLocation EndLoc); + + llvm::ArrayRef getIntExprs() { + return OpenACCClauseWithIntExprs::getIntExprs(); + } + + llvm::ArrayRef getIntExprs() const { + return OpenACCClauseWithIntExprs::getIntExprs(); + } +}; + +/// Represents one of a handful of clauses that have a single integer /// expression. -class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithParams { +class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs { Expr *IntExpr; protected: OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc) - : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), - IntExpr(IntExpr) {} + : OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc), + IntExpr(IntExpr) { + setIntExprs(MutableArrayRef{&this->IntExpr, 1}); + } public: - bool hasIntExpr() const { return IntExpr; } - const Expr *getIntExpr() const { return IntExpr; } - - Expr *getIntExpr() { return IntExpr; }; - - child_range children() { - return child_range(reinterpret_cast(&IntExpr), - reinterpret_cast(&IntExpr + 1)); + bool hasIntExpr() const { return !getIntExprs().empty(); } + const Expr *getIntExpr() const { + return hasIntExpr() ? getIntExprs()[0] : nullptr; } - const_child_range children() const { - return const_child_range(reinterpret_cast(&IntExpr), - reinterpret_cast(&IntExpr + 1)); - } + Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; }; }; class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1bbe76ff6bd2..a95424862e63 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12293,4 +12293,9 @@ def note_acc_int_expr_conversion : Note<"conversion to %select{integral|enumeration}0 type %1">; def err_acc_int_expr_multiple_conversions : Error<"multiple conversions from expression type %0 to an integral type">; +def err_acc_num_gangs_num_args + : Error<"%select{no|too many}0 integer expression arguments provided to " + "OpenACC 'num_gangs' " + "%select{|clause: '%1' directive expects maximum of %2, %3 were " + "provided}0">; } // end of sema component. diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index 520e068f4ffd..dd5792e7ca8c 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -18,6 +18,7 @@ VISIT_CLAUSE(Default) VISIT_CLAUSE(If) VISIT_CLAUSE(Self) +VISIT_CLAUSE(NumGangs) VISIT_CLAUSE(NumWorkers) VISIT_CLAUSE(VectorLength) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 72b2f958a5e6..d3bb04ff7a2c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3644,10 +3644,22 @@ private: /// Parses the clause of the 'bind' argument, which can be a string literal or /// an ID expression. ExprResult ParseOpenACCBindClauseArgument(); + + /// A type to represent the state of parsing after an attempt to parse an + /// OpenACC int-expr. This is useful to determine whether an int-expr list can + /// continue parsing after a failed int-expr. + using OpenACCIntExprParseResult = + std::pair; /// Parses the clause kind of 'int-expr', which can be any integral /// expression. - ExprResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, - SourceLocation Loc); + OpenACCIntExprParseResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, + OpenACCClauseKind CK, + SourceLocation Loc); + /// Parses the argument list for 'num_gangs', which allows up to 3 + /// 'int-expr's. + bool ParseOpenACCIntExprList(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + SourceLocation Loc, + llvm::SmallVectorImpl &IntExprs); /// Parses the 'device-type-list', which is a list of identifiers. bool ParseOpenACCDeviceTypeList(); /// Parses the 'async-argument', which is an integral value with two diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 023722049732..ea28617f79b8 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -93,14 +93,16 @@ public: } unsigned getNumIntExprs() const { - assert((ClauseKind == OpenACCClauseKind::NumWorkers || + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); return std::get(Details).IntExprs.size(); } ArrayRef getIntExprs() { - assert((ClauseKind == OpenACCClauseKind::NumWorkers || + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); return std::get(Details).IntExprs; @@ -134,11 +136,19 @@ public: } void setIntExprDetails(ArrayRef IntExprs) { - assert((ClauseKind == OpenACCClauseKind::NumWorkers || + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}}; } + void setIntExprDetails(llvm::SmallVector &&IntExprs) { + assert((ClauseKind == OpenACCClauseKind::NumGangs || + ClauseKind == OpenACCClauseKind::NumWorkers || + ClauseKind == OpenACCClauseKind::VectorLength) && + "Parsed clause kind does not have a int exprs"); + Details = IntExprDetails{IntExprs}; + } }; SemaOpenACC(Sema &S); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index 75334223e073..6cd5b2880218 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -124,6 +124,16 @@ OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc, OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc); } +OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + ArrayRef IntExprs, + SourceLocation EndLoc) { + void *Mem = C.Allocate( + OpenACCNumGangsClause::totalSizeToAlloc(IntExprs.size())); + return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc); +} + //===----------------------------------------------------------------------===// // OpenACC clauses printing methods //===----------------------------------------------------------------------===// @@ -141,6 +151,12 @@ void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) { OS << "(" << CondExpr << ")"; } +void OpenACCClausePrinter::VisitNumGangsClause(const OpenACCNumGangsClause &C) { + OS << "num_gangs("; + llvm::interleaveComma(C.getIntExprs(), OS); + OS << ")"; +} + void OpenACCClausePrinter::VisitNumWorkersClause( const OpenACCNumWorkersClause &C) { OS << "num_workers(" << C.getIntExpr() << ")"; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8138ae3a244a..c81724f84dd9 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2497,6 +2497,12 @@ void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) { Profiler.VisitStmt(Clause.getConditionExpr()); } +void OpenACCClauseProfiler::VisitNumGangsClause( + const OpenACCNumGangsClause &Clause) { + for (auto *E : Clause.getIntExprs()) + Profiler.VisitStmt(E); +} + void OpenACCClauseProfiler::VisitNumWorkersClause( const OpenACCNumWorkersClause &Clause) { assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr"); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e5a8b285715b..8f0a9a9b0ed0 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -399,6 +399,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { break; case OpenACCClauseKind::If: case OpenACCClauseKind::Self: + case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::VectorLength: // The condition expression will be printed as a part of the 'children', diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 757417f75c96..8a18fca8064e 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -632,16 +632,54 @@ Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { return Clauses; } -ExprResult Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, - OpenACCClauseKind CK, - SourceLocation Loc) { - ExprResult ER = - getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); +Parser::OpenACCIntExprParseResult +Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, + SourceLocation Loc) { + ExprResult ER = ParseAssignmentExpression(); + // If the actual parsing failed, we don't know the state of the parse, so + // don't try to continue. if (!ER.isUsable()) - return ER; + return {ER, OpenACCParseCanContinue::Cannot}; + + // Parsing can continue after the initial assignment expression parsing, so + // even if there was a typo, we can continue. + ER = getActions().CorrectDelayedTyposInExpr(ER); + if (!ER.isUsable()) + return {ER, OpenACCParseCanContinue::Can}; + + return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()), + OpenACCParseCanContinue::Can}; +} + +bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, + OpenACCClauseKind CK, SourceLocation Loc, + llvm::SmallVectorImpl &IntExprs) { + OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc); + + if (!CurResult.first.isUsable() && + CurResult.second == OpenACCParseCanContinue::Cannot) { + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return true; + } + + IntExprs.push_back(CurResult.first.get()); + + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + ExpectAndConsume(tok::comma); + + CurResult = ParseOpenACCIntExpr(DK, CK, Loc); - return getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()); + if (!CurResult.first.isUsable() && + CurResult.second == OpenACCParseCanContinue::Cannot) { + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return true; + } + IntExprs.push_back(CurResult.first.get()); + } + return false; } bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { @@ -761,7 +799,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { ConsumeToken(); return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, GangLoc) - .isInvalid(); + .first.isInvalid(); } if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) && @@ -773,7 +811,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { // This is just the 'num' case where 'num' is optional. return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang, GangLoc) - .isInvalid(); + .first.isInvalid(); } bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) { @@ -946,13 +984,25 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( } break; } - case OpenACCClauseKind::NumGangs: + case OpenACCClauseKind::NumGangs: { + llvm::SmallVector IntExprs; + + if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid, + OpenACCClauseKind::NumGangs, ClauseLoc, + IntExprs)) { + Parens.skipToEnd(); + return OpenACCCanContinue(); + } + ParsedClause.setIntExprDetails(std::move(IntExprs)); + break; + } case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::VectorLength: { ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, - ClauseKind, ClauseLoc); + ClauseKind, ClauseLoc) + .first; if (IntExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); @@ -1017,7 +1067,8 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( : OpenACCSpecialTokenKind::Num, ClauseKind); ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, - ClauseKind, ClauseLoc); + ClauseKind, ClauseLoc) + .first; if (IntExpr.isInvalid()) { Parens.skipToEnd(); return OpenACCCanContinue(); @@ -1081,11 +1132,13 @@ bool Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) { // Consume colon. ConsumeToken(); - ExprResult IntExpr = ParseOpenACCIntExpr( - IsDirective ? OpenACCDirectiveKind::Wait - : OpenACCDirectiveKind::Invalid, - IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, - Loc); + ExprResult IntExpr = + ParseOpenACCIntExpr(IsDirective ? OpenACCDirectiveKind::Wait + : OpenACCDirectiveKind::Invalid, + IsDirective ? OpenACCClauseKind::Invalid + : OpenACCClauseKind::Wait, + Loc) + .first; if (IntExpr.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 190739fa02e9..ba69e71e30a1 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -91,6 +91,7 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, default: return false; } + case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::VectorLength: switch (DirectiveKind) { @@ -230,6 +231,40 @@ SemaOpenACC::ActOnClause(ArrayRef ExistingClauses, getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getConditionExpr(), Clause.getEndLoc()); } + case OpenACCClauseKind::NumGangs: { + // Restrictions only properly implemented on 'compute' constructs, and + // 'compute' constructs are the only construct that can do anything with + // this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + break; + + // There is no prose in the standard that says duplicates aren't allowed, + // but this diagnostic is present in other compilers, as well as makes + // sense. + if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause)) + return nullptr; + + if (Clause.getIntExprs().empty()) + Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args) + << /*NoArgs=*/0; + + unsigned MaxArgs = + (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel || + Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) + ? 3 + : 1; + if (Clause.getIntExprs().size() > MaxArgs) + Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args) + << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs + << Clause.getIntExprs().size(); + + // Create the AST node for the clause even if the number of expressions is + // incorrect. + return OpenACCNumGangsClause::Create( + getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(), + Clause.getIntExprs(), Clause.getEndLoc()); + break; + } case OpenACCClauseKind::NumWorkers: { // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 13f7e9b3fbe3..9404be5a46f3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11162,6 +11162,32 @@ void OpenACCClauseTransform::VisitSelfClause( ParsedClause.getEndLoc()); } +template +void OpenACCClauseTransform::VisitNumGangsClause( + const OpenACCNumGangsClause &C) { + llvm::SmallVector InstantiatedIntExprs; + + for (Expr *CurIntExpr : C.getIntExprs()) { + ExprResult Res = Self.TransformExpr(CurIntExpr); + + if (!Res.isUsable()) + return; + + Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid, + C.getClauseKind(), + C.getBeginLoc(), Res.get()); + if (!Res.isUsable()) + return; + + InstantiatedIntExprs.push_back(Res.get()); + } + + ParsedClause.setIntExprDetails(InstantiatedIntExprs); + NewClause = OpenACCNumGangsClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getIntExprs(), + ParsedClause.getEndLoc()); +} template void OpenACCClauseTransform::VisitNumWorkersClause( const OpenACCNumWorkersClause &C) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 44e23919ea18..d64925676df7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11786,6 +11786,15 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc, CondExpr, EndLoc); } + case OpenACCClauseKind::NumGangs: { + SourceLocation LParenLoc = readSourceLocation(); + unsigned NumClauses = readInt(); + llvm::SmallVector IntExprs; + for (unsigned I = 0; I < NumClauses; ++I) + IntExprs.push_back(readSubExpr()); + return OpenACCNumGangsClause::Create(getContext(), BeginLoc, LParenLoc, + IntExprs, EndLoc); + } case OpenACCClauseKind::NumWorkers: { SourceLocation LParenLoc = readSourceLocation(); Expr *IntExpr = readSubExpr(); @@ -11826,7 +11835,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::DeviceType: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 8a4b36207c47..018b854652a4 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7657,6 +7657,14 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { AddStmt(const_cast(SC->getConditionExpr())); return; } + case OpenACCClauseKind::NumGangs: { + const auto *NGC = cast(C); + writeSourceLocation(NGC->getLParenLoc()); + writeUInt32(NGC->getIntExprs().size()); + for (Expr *E : NGC->getIntExprs()) + AddStmt(E); + return; + } case OpenACCClauseKind::NumWorkers: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); @@ -7697,7 +7705,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::NumGangs: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::DeviceType: diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index ddf40f71701e..799f22b8c120 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -911,16 +911,12 @@ void IntExprParsing() { #pragma acc parallel num_gangs(invalid) {} - // expected-error@+2{{expected ')'}} - // expected-note@+1{{to match this '('}} #pragma acc parallel num_gangs(5, 4) {} - // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}} #pragma acc parallel num_gangs(5) {} - // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}} #pragma acc parallel num_gangs(returns_int()) {} diff --git a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp index 889025c26818..5a4c9f05ee08 100644 --- a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp +++ b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp @@ -88,6 +88,34 @@ void NormalUses() { // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_gangs(some_int(), some_long(), some_short()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: CallExpr{{.*}}'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'int (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'int ()' lvalue Function{{.*}} 'some_int' 'int ()' + // CHECK-NEXT: CallExpr{{.*}}'long' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'long (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'long ()' lvalue Function{{.*}} 'some_long' 'long ()' + // CHECK-NEXT: CallExpr{{.*}}'short' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'short (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'short ()' lvalue Function{{.*}} 'some_short' 'short ()' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels num_gangs(some_int()) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: CallExpr{{.*}}'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'int (*)()' + // CHECK-NEXT: DeclRefExpr{{.*}}'int ()' lvalue Function{{.*}} 'some_int' 'int ()' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt } template @@ -187,6 +215,31 @@ void TemplUses(T t, U u) { // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: CompoundStmt +#pragma acc kernels num_gangs(u) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel num_gangs(u, U::value) + while(true){} + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: DeclRefExpr{{.*}} 'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'U' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}EndMarker + int EndMarker; + // Check the instantiated versions of the above. // CHECK-NEXT: FunctionDecl{{.*}} used TemplUses 'void (CorrectConvert, HasInt)' implicit_instantiation // CHECK-NEXT: TemplateArgument type 'CorrectConvert' @@ -288,6 +341,32 @@ void TemplUses(T t, U u) { // CHECK-NEXT: WhileStmt // CHECK-NEXT: CXXBoolLiteralExpr // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'char' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'char' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator char + // CHECK-NEXT: DeclRefExpr{{.*}} 'HasInt' lvalue ParmVar + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel + // CHECK-NEXT: num_gangs clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'char' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'char' + // CHECK-NEXT: MemberExpr{{.*}} '' .operator char + // CHECK-NEXT: DeclRefExpr{{.*}} 'HasInt' lvalue ParmVar + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const int' lvalue Var{{.*}} 'value' 'const int' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'HasInt' + // CHECK-NEXT: WhileStmt + // CHECK-NEXT: CXXBoolLiteralExpr + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}EndMarker } struct HasInt { diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c new file mode 100644 index 000000000000..cdc6847b47f9 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +short getS(); +void Test() { +#pragma acc kernels num_gangs(1) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1) + while(1); + +#pragma acc parallel num_gangs(1) + while(1); + + // expected-error@+2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'kernels' directive}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels num_gangs(1) num_gangs(2) + while(1); + + // expected-error@+2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'parallel' directive}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel num_gangs(1) num_gangs(2) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'kernels' directive expects maximum of 1, 2 were provided}} +#pragma acc kernels num_gangs(1, getS()) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1, getS()) + while(1); +#pragma acc parallel num_gangs(1, getS()) + while(1); + + struct NotConvertible{} NC; + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(NC) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(1, NC) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(NC, 1) + while(1); + +#pragma acc parallel num_gangs(getS(), 1, getS()) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'parallel' directive expects maximum of 3, 4 were provided}} +#pragma acc parallel num_gangs(getS(), 1, getS(), 1) + while(1); +} diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp new file mode 100644 index 000000000000..ec3df87a0655 --- /dev/null +++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp @@ -0,0 +1,160 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NotConvertible{} NC; +struct Incomplete *SomeIncomplete; // #INCOMPLETE +enum E{} SomeE; +enum class E2{} SomeE2; + +struct CorrectConvert { + operator int(); +} Convert; + +struct ExplicitConvertOnly { + explicit operator int() const; // #EXPL_CONV +} Explicit; + +struct AmbiguousConvert{ + operator int(); // #AMBIG_INT + operator short(); // #AMBIG_SHORT + operator float(); +} Ambiguous; + +short some_short(); +int some_int(); +long some_long(); + +void Test() { +#pragma acc kernels num_gangs(1) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1) + while(1); + +#pragma acc parallel num_gangs(1) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(some_short(), some_int(), some_long()) + while(1); + +#pragma acc parallel num_gangs(some_short(), some_int(), some_long()) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(some_short(), some_int(), some_long(), SomeE) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'parallel' directive expects maximum of 3, 4 were provided}} +#pragma acc parallel num_gangs(some_short(), some_int(), some_long(), SomeE) + while(1); + + // expected-error@+1{{too many integer expression arguments provided to OpenACC 'num_gangs' clause: 'kernels' directive expects maximum of 1, 2 were provided}} +#pragma acc kernels num_gangs(1, 2) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1, 2) + while(1); + +#pragma acc parallel num_gangs(1, 2) + while(1); + + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc parallel num_gangs(Ambiguous) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(NC, SomeE) + while(1); + + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(SomeE, NC) + while(1); + + // expected-error@+3{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel num_gangs(Explicit, NC) + while(1); + + // expected-error@+4{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+2{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(Explicit, NC) + while(1); + + // expected-error@+6{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+4{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc parallel num_gangs(Explicit, NC, Ambiguous) + while(1); + + // expected-error@+7{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+5{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+4{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(Explicit, NC, Ambiguous) + while(1); + // TODO +} + +struct HasInt { + using IntTy = int; + using ShortTy = short; + static constexpr int value = 1; + static constexpr AmbiguousConvert ACValue; + static constexpr ExplicitConvertOnly EXValue; + + operator char(); +}; + +template +void TestInst() { + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(HasInt::Invalid) + while(1); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc parallel num_gangs(T::Invalid) + while(1); + + // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel num_gangs(1, HasInt::Invalid) + while(1); + + // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel num_gangs(T::Invalid, 1) + while(1); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(1, HasInt::Invalid) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(T::Invalid, 1) + while(1); + +#pragma acc parallel num_gangs(T::value, typename T::IntTy{}) + while(1); + + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} +#pragma acc serial num_gangs(T::value, typename T::IntTy{}) + while(1); +} + +void Inst() { + TestInst(); // #INST +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index cbc1d85bb33d..74163f30e19b 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2803,6 +2803,10 @@ void OpenACCClauseEnqueue::VisitVectorLengthClause( const OpenACCVectorLengthClause &C) { Visitor.AddStmt(C.getIntExpr()); } +void OpenACCClauseEnqueue::VisitNumGangsClause(const OpenACCNumGangsClause &C) { + for (Expr *IE : C.getIntExprs()) + Visitor.AddStmt(IE); +} } // namespace void EnqueueVisitor::EnqueueChildren(const OpenACCClause *C) { -- GitLab From 947cd677083d69412b5a900d8fad59e3062c4875 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 22 Apr 2024 11:59:54 -0400 Subject: [PATCH 181/357] [C23] Select the correct promoted type for a bit-field (#89254) Bit-fields of bit-precise integer type do not promote to int, but instead promote to the type of the field. Fixes #87641 --- clang/docs/ReleaseNotes.rst | 3 ++ clang/lib/AST/ASTContext.cpp | 8 ++++ clang/lib/AST/Interp/IntegralAP.h | 5 ++- clang/test/Sema/bitint-bitfield-promote.c | 54 +++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 clang/test/Sema/bitint-bitfield-promote.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index db5830a63715..009531bae8a9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -179,6 +179,9 @@ C23 Feature Support - Clang now supports `N3018 The constexpr specifier for object definitions` `_. +- Properly promote bit-fields of bit-precise integer types to the field's type + rather than to ``int``. #GH87641 + Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b974fc28283c..b36fb5523af5 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7241,6 +7241,14 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { // We perform that promotion here to match GCC and C++. // FIXME: C does not permit promotion of an enum bit-field whose rank is // greater than that of 'int'. We perform that promotion to match GCC. + // + // C23 6.3.1.1p2: + // The value from a bit-field of a bit-precise integer type is converted to + // the corresponding bit-precise integer type. (The rest is the same as in + // C11.) + if (QualType QT = Field->getType(); QT->isBitIntType()) + return QT; + if (BitWidth < IntSize) return IntTy; diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index bab9774288bf..fb7ee1451571 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -154,7 +154,10 @@ public: } IntegralAP truncate(unsigned BitWidth) const { - return IntegralAP(V.trunc(BitWidth)); + if constexpr (Signed) + return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth())); + else + return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth())); } IntegralAP toUnsigned() const { diff --git a/clang/test/Sema/bitint-bitfield-promote.c b/clang/test/Sema/bitint-bitfield-promote.c new file mode 100644 index 000000000000..e82e94975cfd --- /dev/null +++ b/clang/test/Sema/bitint-bitfield-promote.c @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s + +// GH87641 noticed that integer promotion of a bit-field of bit-precise integer +// type was promoting to int rather than the type of the bit-field. +struct S { + unsigned _BitInt(7) x : 2; + unsigned _BitInt(2) y : 2; + unsigned _BitInt(72) z : 28; + _BitInt(31) a : 12; + _BitInt(33) b : 33; +}; + +// We don't have to worry about promotion cases where the bit-precise type is +// smaller than the width of the bit-field; that can't happen. +struct T { + unsigned _BitInt(28) oh_no : 72; // expected-error {{width of bit-field 'oh_no' (72 bits) exceeds the width of its type (28 bits)}} +}; + +static_assert( + _Generic(+(struct S){}.x, + int : 0, + unsigned _BitInt(7) : 1, + unsigned _BitInt(2) : 2 + ) == 1); + +static_assert( + _Generic(+(struct S){}.y, + int : 0, + unsigned _BitInt(7) : 1, + unsigned _BitInt(2) : 2 + ) == 2); + +static_assert( + _Generic(+(struct S){}.z, + int : 0, + unsigned _BitInt(72) : 1, + unsigned _BitInt(28) : 2 + ) == 1); + +static_assert( + _Generic(+(struct S){}.a, + int : 0, + _BitInt(31) : 1, + _BitInt(12) : 2, + unsigned _BitInt(31) : 3 + ) == 1); + +static_assert( + _Generic(+(struct S){}.b, + int : 0, + long long : 1, + _BitInt(33) : 2, + unsigned _BitInt(33) : 3 + ) == 2); -- GitLab From 583795e1ca7c331a9e5a12a7829b572625321f92 Mon Sep 17 00:00:00 2001 From: Alex MacLean Date: Mon, 22 Apr 2024 09:01:01 -0700 Subject: [PATCH 182/357] [NVPTX][NFCI] Use DataLayout to determine short shared/local/const pointers (#89404) Use the datalayout directly to determine the correct `cvta` instruction for converting shared/local/const pointers. This is cleaner as it eliminates the need to keep a redundant copy of this info in the TM and makes clear which address spaces short pointers are applicable for. --- llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp | 2 +- llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 51 ++++++++++---------- llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h | 1 - llvm/lib/Target/NVPTX/NVPTXInstrInfo.td | 6 ++- llvm/lib/Target/NVPTX/NVPTXIntrinsics.td | 37 +++++++------- llvm/lib/Target/NVPTX/NVPTXPeephole.cpp | 6 +-- llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp | 3 +- llvm/lib/Target/NVPTX/NVPTXTargetMachine.h | 3 -- 8 files changed, 54 insertions(+), 55 deletions(-) diff --git a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp index c34472c21ccb..10ae81e0460e 100644 --- a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp @@ -50,7 +50,7 @@ void NVPTXFrameLowering::emitPrologue(MachineFunction &MF, bool Is64Bit = static_cast(MF.getTarget()).is64Bit(); unsigned CvtaLocalOpcode = - (Is64Bit ? NVPTX::cvta_local_yes_64 : NVPTX::cvta_local_yes); + (Is64Bit ? NVPTX::cvta_local_64 : NVPTX::cvta_local); unsigned MovDepotOpcode = (Is64Bit ? NVPTX::MOV_DEPOT_ADDR_64 : NVPTX::MOV_DEPOT_ADDR); if (!MR.use_empty(NRI->getFrameRegister(MF))) { diff --git a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp index 3ff8994602e1..a362709c98ef 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp @@ -74,10 +74,6 @@ bool NVPTXDAGToDAGISel::allowUnsafeFPMath() const { return TL->allowUnsafeFPMath(*MF); } -bool NVPTXDAGToDAGISel::useShortPointers() const { - return TM.useShortPointers(); -} - /// Select - Select instructions not customized! Used for /// expanded, promoted and normal instructions. void NVPTXDAGToDAGISel::Select(SDNode *N) { @@ -768,22 +764,25 @@ void NVPTXDAGToDAGISel::SelectAddrSpaceCast(SDNode *N) { switch (SrcAddrSpace) { default: report_fatal_error("Bad address space in addrspacecast"); case ADDRESS_SPACE_GLOBAL: - Opc = TM.is64Bit() ? NVPTX::cvta_global_yes_64 : NVPTX::cvta_global_yes; + Opc = TM.is64Bit() ? NVPTX::cvta_global_64 : NVPTX::cvta_global; break; case ADDRESS_SPACE_SHARED: - Opc = TM.is64Bit() ? (useShortPointers() ? NVPTX::cvta_shared_yes_6432 - : NVPTX::cvta_shared_yes_64) - : NVPTX::cvta_shared_yes; + Opc = TM.is64Bit() ? (TM.getPointerSizeInBits(SrcAddrSpace) == 32 + ? NVPTX::cvta_shared_6432 + : NVPTX::cvta_shared_64) + : NVPTX::cvta_shared; break; case ADDRESS_SPACE_CONST: - Opc = TM.is64Bit() ? (useShortPointers() ? NVPTX::cvta_const_yes_6432 - : NVPTX::cvta_const_yes_64) - : NVPTX::cvta_const_yes; + Opc = TM.is64Bit() ? (TM.getPointerSizeInBits(SrcAddrSpace) == 32 + ? NVPTX::cvta_const_6432 + : NVPTX::cvta_const_64) + : NVPTX::cvta_const; break; case ADDRESS_SPACE_LOCAL: - Opc = TM.is64Bit() ? (useShortPointers() ? NVPTX::cvta_local_yes_6432 - : NVPTX::cvta_local_yes_64) - : NVPTX::cvta_local_yes; + Opc = TM.is64Bit() ? (TM.getPointerSizeInBits(SrcAddrSpace) == 32 + ? NVPTX::cvta_local_6432 + : NVPTX::cvta_local_64) + : NVPTX::cvta_local; break; } ReplaceNode(N, CurDAG->getMachineNode(Opc, SDLoc(N), N->getValueType(0), @@ -797,23 +796,25 @@ void NVPTXDAGToDAGISel::SelectAddrSpaceCast(SDNode *N) { switch (DstAddrSpace) { default: report_fatal_error("Bad address space in addrspacecast"); case ADDRESS_SPACE_GLOBAL: - Opc = TM.is64Bit() ? NVPTX::cvta_to_global_yes_64 - : NVPTX::cvta_to_global_yes; + Opc = TM.is64Bit() ? NVPTX::cvta_to_global_64 : NVPTX::cvta_to_global; break; case ADDRESS_SPACE_SHARED: - Opc = TM.is64Bit() ? (useShortPointers() ? NVPTX::cvta_to_shared_yes_3264 - : NVPTX::cvta_to_shared_yes_64) - : NVPTX::cvta_to_shared_yes; + Opc = TM.is64Bit() ? (TM.getPointerSizeInBits(DstAddrSpace) == 32 + ? NVPTX::cvta_to_shared_3264 + : NVPTX::cvta_to_shared_64) + : NVPTX::cvta_to_shared; break; case ADDRESS_SPACE_CONST: - Opc = TM.is64Bit() ? (useShortPointers() ? NVPTX::cvta_to_const_yes_3264 - : NVPTX::cvta_to_const_yes_64) - : NVPTX::cvta_to_const_yes; + Opc = TM.is64Bit() ? (TM.getPointerSizeInBits(DstAddrSpace) == 32 + ? NVPTX::cvta_to_const_3264 + : NVPTX::cvta_to_const_64) + : NVPTX::cvta_to_const; break; case ADDRESS_SPACE_LOCAL: - Opc = TM.is64Bit() ? (useShortPointers() ? NVPTX::cvta_to_local_yes_3264 - : NVPTX::cvta_to_local_yes_64) - : NVPTX::cvta_to_local_yes; + Opc = TM.is64Bit() ? (TM.getPointerSizeInBits(DstAddrSpace) == 32 + ? NVPTX::cvta_to_local_3264 + : NVPTX::cvta_to_local_64) + : NVPTX::cvta_to_local; break; case ADDRESS_SPACE_PARAM: Opc = TM.is64Bit() ? NVPTX::nvvm_ptr_gen_to_param_64 diff --git a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h index 84c8432047ca..10822f87cef3 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h +++ b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h @@ -36,7 +36,6 @@ class LLVM_LIBRARY_VISIBILITY NVPTXDAGToDAGISel : public SelectionDAGISel { bool useF32FTZ() const; bool allowFMA() const; bool allowUnsafeFPMath() const; - bool useShortPointers() const; public: static char ID; diff --git a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td index cd8546005c02..931292c7fd60 100644 --- a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td +++ b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td @@ -160,6 +160,7 @@ def hasHWROT32 : Predicate<"Subtarget->hasHWROT32()">; def noHWROT32 : Predicate<"!Subtarget->hasHWROT32()">; def True : Predicate<"true">; +def False : Predicate<"false">; class hasPTX: Predicate<"Subtarget->getPTXVersion() >= " # version>; class hasSM: Predicate<"Subtarget->getSmVersion() >= " # version>; @@ -171,7 +172,10 @@ def hasSM90a : Predicate<"Subtarget->getFullSmVersion() == 901">; def hasSHFL : Predicate<"!(Subtarget->getSmVersion() >= 70" "&& Subtarget->getPTXVersion() >= 64)">; -def useShortPtr : Predicate<"useShortPointers()">; +def useShortPtrLocal : Predicate<"TM.is64Bit() && TM.getPointerSizeInBits(ADDRESS_SPACE_LOCAL) == 32">; +def useShortPtrShared : Predicate<"TM.is64Bit() && TM.getPointerSizeInBits(ADDRESS_SPACE_SHARED) == 32">; +def useShortPtrConst : Predicate<"TM.is64Bit() && TM.getPointerSizeInBits(ADDRESS_SPACE_CONST) == 32">; + def useFP16Math: Predicate<"Subtarget->allowFP16Math()">; def hasBF16Math: Predicate<"Subtarget->hasBF16Math()">; diff --git a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td index c0c53380a13e..ec9170b4e41e 100644 --- a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td +++ b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td @@ -2407,46 +2407,45 @@ defm INT_PTX_LDG_G_v4f32_ELE : VLDG_G_ELE_V4<"v4.f32 \t{{$dst1, $dst2, $dst3, $dst4}}, [$src];", Float32Regs>; -multiclass NG_TO_G { - def _yes : NVPTXInst<(outs Int32Regs:$result), (ins Int32Regs:$src), +multiclass NG_TO_G { + def "" : NVPTXInst<(outs Int32Regs:$result), (ins Int32Regs:$src), !strconcat("cvta.", Str, ".u32 \t$result, $src;"), [(set Int32Regs:$result, (Intrin Int32Regs:$src))]>; - def _yes_64 : NVPTXInst<(outs Int64Regs:$result), (ins Int64Regs:$src), + def _64 : NVPTXInst<(outs Int64Regs:$result), (ins Int64Regs:$src), !strconcat("cvta.", Str, ".u64 \t$result, $src;"), [(set Int64Regs:$result, (Intrin Int64Regs:$src))]>; - def _yes_6432 : NVPTXInst<(outs Int64Regs:$result), (ins Int32Regs:$src), + def _6432 : NVPTXInst<(outs Int64Regs:$result), (ins Int32Regs:$src), "{{ .reg .b64 %tmp;\n\t" #" cvt.u64.u32 \t%tmp, $src;\n\t" #" cvta." # Str # ".u64 \t$result, %tmp; }}", [(set Int64Regs:$result, (Intrin Int32Regs:$src))]>, - Requires<[useShortPtr]>; + Requires<[ShortPtr]>; } -multiclass G_TO_NG { - def _yes : NVPTXInst<(outs Int32Regs:$result), (ins Int32Regs:$src), +multiclass G_TO_NG { + def "" : NVPTXInst<(outs Int32Regs:$result), (ins Int32Regs:$src), !strconcat("cvta.to.", Str, ".u32 \t$result, $src;"), [(set Int32Regs:$result, (Intrin Int32Regs:$src))]>; - def _yes_64 : NVPTXInst<(outs Int64Regs:$result), (ins Int64Regs:$src), + def _64 : NVPTXInst<(outs Int64Regs:$result), (ins Int64Regs:$src), !strconcat("cvta.to.", Str, ".u64 \t$result, $src;"), [(set Int64Regs:$result, (Intrin Int64Regs:$src))]>; - def _yes_3264 : NVPTXInst<(outs Int32Regs:$result), (ins Int64Regs:$src), + def _3264 : NVPTXInst<(outs Int32Regs:$result), (ins Int64Regs:$src), "{{ .reg .b64 %tmp;\n\t" #" cvta.to." # Str # ".u64 \t%tmp, $src;\n\t" #" cvt.u32.u64 \t$result, %tmp; }}", [(set Int32Regs:$result, (Intrin Int64Regs:$src))]>, - Requires<[useShortPtr]>; + Requires<[ShortPtr]>; } -defm cvta_local : NG_TO_G<"local", int_nvvm_ptr_local_to_gen>; -defm cvta_shared : NG_TO_G<"shared", int_nvvm_ptr_shared_to_gen>; -defm cvta_global : NG_TO_G<"global", int_nvvm_ptr_global_to_gen>; -defm cvta_const : NG_TO_G<"const", int_nvvm_ptr_constant_to_gen>; - -defm cvta_to_local : G_TO_NG<"local", int_nvvm_ptr_gen_to_local>; -defm cvta_to_shared : G_TO_NG<"shared", int_nvvm_ptr_gen_to_shared>; -defm cvta_to_global : G_TO_NG<"global", int_nvvm_ptr_gen_to_global>; -defm cvta_to_const : G_TO_NG<"const", int_nvvm_ptr_gen_to_constant>; +defm cvta_local : NG_TO_G<"local", int_nvvm_ptr_local_to_gen, useShortPtrLocal>; +defm cvta_shared : NG_TO_G<"shared", int_nvvm_ptr_shared_to_gen, useShortPtrShared>; +defm cvta_global : NG_TO_G<"global", int_nvvm_ptr_global_to_gen, False>; +defm cvta_const : NG_TO_G<"const", int_nvvm_ptr_constant_to_gen, useShortPtrConst>; +defm cvta_to_local : G_TO_NG<"local", int_nvvm_ptr_gen_to_local, useShortPtrLocal>; +defm cvta_to_shared : G_TO_NG<"shared", int_nvvm_ptr_gen_to_shared, useShortPtrShared>; +defm cvta_to_global : G_TO_NG<"global", int_nvvm_ptr_gen_to_global, False>; +defm cvta_to_const : G_TO_NG<"const", int_nvvm_ptr_gen_to_constant, useShortPtrConst>; // nvvm.ptr.gen.to.param def nvvm_ptr_gen_to_param : NVPTXInst<(outs Int32Regs:$result), diff --git a/llvm/lib/Target/NVPTX/NVPTXPeephole.cpp b/llvm/lib/Target/NVPTX/NVPTXPeephole.cpp index 0968701737e8..f2f547da88c7 100644 --- a/llvm/lib/Target/NVPTX/NVPTXPeephole.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXPeephole.cpp @@ -22,7 +22,7 @@ // // It will transform the following pattern // %0 = LEA_ADDRi64 %VRFrame64, 4 -// %1 = cvta_to_local_yes_64 %0 +// %1 = cvta_to_local_64 %0 // // into // %1 = LEA_ADDRi64 %VRFrameLocal64, 4 @@ -76,8 +76,8 @@ static bool isCVTAToLocalCombinationCandidate(MachineInstr &Root) { auto &MBB = *Root.getParent(); auto &MF = *MBB.getParent(); // Check current instruction is cvta.to.local - if (Root.getOpcode() != NVPTX::cvta_to_local_yes_64 && - Root.getOpcode() != NVPTX::cvta_to_local_yes) + if (Root.getOpcode() != NVPTX::cvta_to_local_64 && + Root.getOpcode() != NVPTX::cvta_to_local) return false; auto &Op = Root.getOperand(1); diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp index 78f48652c992..2a47c16a6bce 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -132,8 +132,7 @@ NVPTXTargetMachine::NVPTXTargetMachine(const Target &T, const Triple &TT, : LLVMTargetMachine(T, computeDataLayout(is64bit, UseShortPointersOpt), TT, CPU, FS, Options, Reloc::PIC_, getEffectiveCodeModel(CM, CodeModel::Small), OL), - is64bit(is64bit), UseShortPointers(UseShortPointersOpt), - TLOF(std::make_unique()), + is64bit(is64bit), TLOF(std::make_unique()), Subtarget(TT, std::string(CPU), std::string(FS), *this), StrPool(StrAlloc) { if (TT.getOS() == Triple::NVCL) diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h index 9e6bf929badb..870ea20c26f3 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h +++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.h @@ -24,8 +24,6 @@ namespace llvm { /// class NVPTXTargetMachine : public LLVMTargetMachine { bool is64bit; - // Use 32-bit pointers for accessing const/local/short AS. - bool UseShortPointers; std::unique_ptr TLOF; NVPTX::DrvInterface drvInterface; NVPTXSubtarget Subtarget; @@ -46,7 +44,6 @@ public: } const NVPTXSubtarget *getSubtargetImpl() const { return &Subtarget; } bool is64Bit() const { return is64bit; } - bool useShortPointers() const { return UseShortPointers; } NVPTX::DrvInterface getDrvInterface() const { return drvInterface; } UniqueStringSaver &getStrPool() const { return const_cast(StrPool); -- GitLab From 60535229dd640efacc9d3dfc1cddecc718640067 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Mon, 22 Apr 2024 18:01:32 +0200 Subject: [PATCH 183/357] [RISCV] Precommit stack protector checks for Linux and Android (#87679) Upcoming patches will add TP relative stack checks for Android, and Linux currently uses the default GOT based stack protector. --- .../CodeGen/RISCV/stack-protector-target.ll | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/stack-protector-target.ll b/llvm/test/CodeGen/RISCV/stack-protector-target.ll index 13abde7878f3..50531d384982 100644 --- a/llvm/test/CodeGen/RISCV/stack-protector-target.ll +++ b/llvm/test/CodeGen/RISCV/stack-protector-target.ll @@ -2,9 +2,32 @@ ;; Test target-specific stack cookie location. ; +; RUN: llc -mtriple=riscv64-linux < %s | FileCheck --check-prefix=LINUX-RISCV64 %s ; RUN: llc -mtriple=riscv64-fuchsia < %s | FileCheck --check-prefix=FUCHSIA-RISCV64 %s +; RUN: llc -mtriple=riscv64-android < %s | FileCheck --check-prefix=ANDROID-RISCV64 %s define void @func() sspreq nounwind { +; LINUX-RISCV64-LABEL: func: +; LINUX-RISCV64: # %bb.0: +; LINUX-RISCV64-NEXT: addi sp, sp, -32 +; LINUX-RISCV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; LINUX-RISCV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; LINUX-RISCV64-NEXT: lui s0, %hi(__stack_chk_guard) +; LINUX-RISCV64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) +; LINUX-RISCV64-NEXT: sd a0, 8(sp) +; LINUX-RISCV64-NEXT: addi a0, sp, 4 +; LINUX-RISCV64-NEXT: call capture +; LINUX-RISCV64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) +; LINUX-RISCV64-NEXT: ld a1, 8(sp) +; LINUX-RISCV64-NEXT: bne a0, a1, .LBB0_2 +; LINUX-RISCV64-NEXT: # %bb.1: +; LINUX-RISCV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; LINUX-RISCV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; LINUX-RISCV64-NEXT: addi sp, sp, 32 +; LINUX-RISCV64-NEXT: ret +; LINUX-RISCV64-NEXT: .LBB0_2: +; LINUX-RISCV64-NEXT: call __stack_chk_fail +; ; FUCHSIA-RISCV64-LABEL: func: ; FUCHSIA-RISCV64: # %bb.0: ; FUCHSIA-RISCV64-NEXT: addi sp, sp, -32 @@ -22,6 +45,27 @@ define void @func() sspreq nounwind { ; FUCHSIA-RISCV64-NEXT: ret ; FUCHSIA-RISCV64-NEXT: .LBB0_2: # %CallStackCheckFailBlk ; FUCHSIA-RISCV64-NEXT: call __stack_chk_fail +; +; ANDROID-RISCV64-LABEL: func: +; ANDROID-RISCV64: # %bb.0: +; ANDROID-RISCV64-NEXT: addi sp, sp, -32 +; ANDROID-RISCV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; ANDROID-RISCV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; ANDROID-RISCV64-NEXT: lui s0, %hi(__stack_chk_guard) +; ANDROID-RISCV64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) +; ANDROID-RISCV64-NEXT: sd a0, 8(sp) +; ANDROID-RISCV64-NEXT: addi a0, sp, 4 +; ANDROID-RISCV64-NEXT: call capture +; ANDROID-RISCV64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) +; ANDROID-RISCV64-NEXT: ld a1, 8(sp) +; ANDROID-RISCV64-NEXT: bne a0, a1, .LBB0_2 +; ANDROID-RISCV64-NEXT: # %bb.1: +; ANDROID-RISCV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; ANDROID-RISCV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; ANDROID-RISCV64-NEXT: addi sp, sp, 32 +; ANDROID-RISCV64-NEXT: ret +; ANDROID-RISCV64-NEXT: .LBB0_2: +; ANDROID-RISCV64-NEXT: call __stack_chk_fail %1 = alloca i32, align 4 call void @capture(ptr %1) ret void -- GitLab From 7c581b554efa7c720b780f721877107ae0fc78ff Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 22 Apr 2024 12:04:13 -0400 Subject: [PATCH 184/357] [Clang][Sema] Remove unused function after #88731 (#89618) Removes an unused static function `IsOverloaded` from `SemaOverload.cpp` that is unused after #88731. --- clang/lib/Sema/SemaOverload.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index a2763e331357..04cd9e78739d 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14261,12 +14261,6 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, OverloadResult, AllowTypoCorrection); } -static bool IsOverloaded(const UnresolvedSetImpl &Functions) { - return Functions.size() > 1 || - (Functions.size() == 1 && - isa((*Functions.begin())->getUnderlyingDecl())); -} - ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, NestedNameSpecifierLoc NNSLoc, DeclarationNameInfo DNI, -- GitLab From 6ad22c879aab88b6bb0531eeb3a6708a82f88cf6 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 22 Apr 2024 09:24:22 -0700 Subject: [PATCH 185/357] [compiler-rt][ctx_instr] Add `ctx_profile` component (#89304) Add the component structure for contextual instrumented PGO and the bump allocator + test. (Tracking Issue: #89287, RFC referenced there) --- compiler-rt/CMakeLists.txt | 2 + .../cmake/Modules/AllSupportedArchDefs.cmake | 1 + compiler-rt/cmake/config-ix.cmake | 11 +++ compiler-rt/lib/CMakeLists.txt | 4 ++ compiler-rt/lib/ctx_profile/CMakeLists.txt | 28 ++++++++ .../lib/ctx_profile/CtxInstrProfiling.cpp | 40 +++++++++++ .../lib/ctx_profile/CtxInstrProfiling.h | 55 +++++++++++++++ .../lib/ctx_profile/tests/CMakeLists.txt | 70 +++++++++++++++++++ .../tests/CtxInstrProfilingTest.cpp | 22 ++++++ compiler-rt/lib/ctx_profile/tests/driver.cpp | 14 ++++ 10 files changed, 247 insertions(+) create mode 100644 compiler-rt/lib/ctx_profile/CMakeLists.txt create mode 100644 compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp create mode 100644 compiler-rt/lib/ctx_profile/CtxInstrProfiling.h create mode 100644 compiler-rt/lib/ctx_profile/tests/CMakeLists.txt create mode 100644 compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp create mode 100644 compiler-rt/lib/ctx_profile/tests/driver.cpp diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 8649507ce1c7..6ce451e3cac2 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -50,6 +50,8 @@ option(COMPILER_RT_BUILD_LIBFUZZER "Build libFuzzer" ON) mark_as_advanced(COMPILER_RT_BUILD_LIBFUZZER) option(COMPILER_RT_BUILD_PROFILE "Build profile runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_PROFILE) +option(COMPILER_RT_BUILD_CTX_PROFILE "Build ctx profile runtime" ON) +mark_as_advanced(COMPILER_RT_BUILD_CTX_PROFILE) option(COMPILER_RT_BUILD_MEMPROF "Build memory profiling runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_MEMPROF) option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" OFF) diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index 423171532c20..2fe06273a814 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -66,6 +66,7 @@ set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} ${RISCV32} ${RISCV64} ${LOONGARCH64}) +set(ALL_CTX_PROFILE_SUPPORTED_ARCH ${X86_64}) set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X} ${LOONGARCH64} ${RISCV64}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index b281ac64f5d5..ba740af9e1d6 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -632,6 +632,9 @@ if(APPLE) list_intersect(PROFILE_SUPPORTED_ARCH ALL_PROFILE_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) + list_intersect(CTX_PROFILE_SUPPORTED_ARCH + ALL_CTX_PROFILE_SUPPORTED_ARCH + SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(TSAN_SUPPORTED_ARCH ALL_TSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -678,6 +681,7 @@ else() filter_available_targets(HWASAN_SUPPORTED_ARCH ${ALL_HWASAN_SUPPORTED_ARCH}) filter_available_targets(MEMPROF_SUPPORTED_ARCH ${ALL_MEMPROF_SUPPORTED_ARCH}) filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH}) + filter_available_targets(CTX_PROFILE_SUPPORTED_ARCH ${ALL_CTX_PROFILE_SUPPORTED_ARCH}) filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH}) filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH}) filter_available_targets(SAFESTACK_SUPPORTED_ARCH @@ -803,6 +807,13 @@ else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() +if (COMPILER_RT_HAS_SANITIZER_COMMON AND CTX_PROFILE_SUPPORTED_ARCH AND + OS_NAME MATCHES "Linux") + set(COMPILER_RT_HAS_CTX_PROFILE TRUE) +else() + set(COMPILER_RT_HAS_CTX_PROFILE FALSE) +endif() + if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH) if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD") set(COMPILER_RT_HAS_TSAN TRUE) diff --git a/compiler-rt/lib/CMakeLists.txt b/compiler-rt/lib/CMakeLists.txt index 43ba9a102c84..f9e96563b880 100644 --- a/compiler-rt/lib/CMakeLists.txt +++ b/compiler-rt/lib/CMakeLists.txt @@ -51,6 +51,10 @@ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) compiler_rt_build_runtime(profile) endif() +if(COMPILER_RT_BUILD_CTX_PROFILE AND COMPILER_RT_HAS_CTX_PROFILE) + compiler_rt_build_runtime(ctx_profile) +endif() + if(COMPILER_RT_BUILD_XRAY) compiler_rt_build_runtime(xray) endif() diff --git a/compiler-rt/lib/ctx_profile/CMakeLists.txt b/compiler-rt/lib/ctx_profile/CMakeLists.txt new file mode 100644 index 000000000000..621b7d30b76d --- /dev/null +++ b/compiler-rt/lib/ctx_profile/CMakeLists.txt @@ -0,0 +1,28 @@ +add_compiler_rt_component(ctx_profile) + +set(CTX_PROFILE_SOURCES + CtxInstrProfiling.cpp + ) + +set(CTX_PROFILE_HEADERS + CtxInstrProfiling.h + ) + +include_directories(..) +include_directories(../../include) + +# We don't use the C++ Standard Library here, so avoid including it by mistake. +append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ EXTRA_FLAGS) + +add_compiler_rt_runtime(clang_rt.ctx_profile + STATIC + ARCHS ${CTX_PROFILE_SUPPORTED_ARCH} + OBJECT_LIBS RTSanitizerCommon RTSanitizerCommonLibc + CFLAGS ${EXTRA_FLAGS} + SOURCES ${CTX_PROFILE_SOURCES} + ADDITIONAL_HEADERS ${CTX_PROFILE_HEADERS} + PARENT_TARGET ctx_profile) + +if(COMPILER_RT_INCLUDE_TESTS) + add_subdirectory(tests) +endif() diff --git a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp new file mode 100644 index 000000000000..7620ce92f7eb --- /dev/null +++ b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp @@ -0,0 +1,40 @@ +//===- CtxInstrProfiling.cpp - contextual instrumented PGO ----------------===// +// +// 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 "CtxInstrProfiling.h" +#include "sanitizer_common/sanitizer_allocator_internal.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_dense_map.h" +#include "sanitizer_common/sanitizer_mutex.h" +#include "sanitizer_common/sanitizer_placement_new.h" +#include "sanitizer_common/sanitizer_thread_safety.h" + +#include + +using namespace __ctx_profile; + +// FIXME(mtrofin): use malloc / mmap instead of sanitizer common APIs to reduce +// the dependency on the latter. +Arena *Arena::allocateNewArena(size_t Size, Arena *Prev) { + assert(!Prev || Prev->Next == nullptr); + Arena *NewArena = + new (__sanitizer::InternalAlloc(Size + sizeof(Arena))) Arena(Size); + if (Prev) + Prev->Next = NewArena; + return NewArena; +} + +void Arena::freeArenaList(Arena *&A) { + assert(A); + for (auto *I = A; I != nullptr;) { + auto *Current = I; + I = I->Next; + __sanitizer::InternalFree(Current); + } + A = nullptr; +} diff --git a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h new file mode 100644 index 000000000000..c1789c32a64c --- /dev/null +++ b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h @@ -0,0 +1,55 @@ +/*===- CtxInstrProfiling.h- Contextual instrumentation-based PGO ---------===*\ +|* +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +|* See https://llvm.org/LICENSE.txt for license information. +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef CTX_PROFILE_CTXINSTRPROFILING_H_ +#define CTX_PROFILE_CTXINSTRPROFILING_H_ + +#include + +namespace __ctx_profile { + +/// Arena (bump allocator) forming a linked list. Intentionally not thread safe. +/// Allocation and de-allocation happen using sanitizer APIs. We make that +/// explicit. +class Arena final { +public: + // When allocating a new Arena, optionally specify an existing one to append + // to, assumed to be the last in the Arena list. We only need to support + // appending to the arena list. + static Arena *allocateNewArena(size_t Size, Arena *Prev = nullptr); + static void freeArenaList(Arena *&A); + + uint64_t size() const { return Size; } + + // Allocate S bytes or return nullptr if we don't have that many available. + char *tryBumpAllocate(size_t S) { + if (Pos + S > Size) + return nullptr; + Pos += S; + return start() + (Pos - S); + } + + Arena *next() const { return Next; } + + // the beginning of allocatable memory. + const char *start() const { return const_cast(this)->start(); } + const char *pos() const { return start() + Pos; } + +private: + explicit Arena(uint32_t Size) : Size(Size) {} + ~Arena() = delete; + + char *start() { return reinterpret_cast(&this[1]); } + + Arena *Next = nullptr; + uint64_t Pos = 0; + const uint64_t Size; +}; + +} // namespace __ctx_profile +#endif // CTX_PROFILE_CTXINSTRPROFILING_H_ diff --git a/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt b/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt new file mode 100644 index 000000000000..93b41b838445 --- /dev/null +++ b/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt @@ -0,0 +1,70 @@ +include(CheckCXXCompilerFlag) +include(CompilerRTCompile) +include(CompilerRTLink) + +set(CTX_PROFILE_UNITTEST_CFLAGS + ${COMPILER_RT_UNITTEST_CFLAGS} + ${COMPILER_RT_GTEST_CFLAGS} + ${COMPILER_RT_GMOCK_CFLAGS} + ${SANITIZER_TEST_CXX_CFLAGS} + -I${COMPILER_RT_SOURCE_DIR}/lib/ + -DSANITIZER_COMMON_NO_REDEFINE_BUILTINS + -O2 + -g + -fno-rtti + -Wno-pedantic + -fno-omit-frame-pointer) + +# Suppress warnings for gmock variadic macros for clang and gcc respectively. +append_list_if(SUPPORTS_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS_FLAG -Wno-gnu-zero-variadic-macro-arguments CTX_PROFILE_UNITTEST_CFLAGS) +append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros CTX_PROFILE_UNITTEST_CFLAGS) + +file(GLOB PROFILE_HEADERS ../*.h) + +set(CTX_PROFILE_SOURCES + ../CtxInstrProfiling.cpp) + +set(CTX_PROFILE_UNITTESTS + CtxInstrProfilingTest.cpp + driver.cpp) + +include_directories(../../../include) + +set(CTX_PROFILE_UNIT_TEST_HEADERS + ${CTX_PROFILE_HEADERS}) + +set(CTX_PROFILE_UNITTEST_LINK_FLAGS + ${COMPILER_RT_UNITTEST_LINK_FLAGS}) + +list(APPEND CTX_PROFILE_UNITTEST_LINK_FLAGS -pthread) + +set(CTX_PROFILE_UNITTEST_LINK_LIBRARIES + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_TEST_CXX_LIBRARIES}) +list(APPEND CTX_PROFILE_UNITTEST_LINK_LIBRARIES "dl") + +if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST CTX_PROFILE_SUPPORTED_ARCH) + # Profile unit tests are only run on the host machine. + set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) + + add_executable(CtxProfileUnitTests + ${CTX_PROFILE_UNITTESTS} + ${COMPILER_RT_GTEST_SOURCE} + ${COMPILER_RT_GMOCK_SOURCE} + ${CTX_PROFILE_SOURCES} + $ + $ + $ + $ + $) + set_target_compile_flags(CtxProfileUnitTests ${CTX_PROFILE_UNITTEST_CFLAGS}) + set_target_link_flags(CtxProfileUnitTests ${CTX_PROFILE_UNITTEST_LINK_FLAGS}) + target_link_libraries(CtxProfileUnitTests ${CTX_PROFILE_UNITTEST_LINK_LIBRARIES}) + + if (TARGET cxx-headers OR HAVE_LIBCXX) + add_dependencies(CtxProfileUnitTests cxx-headers) + endif() + + set_target_properties(CtxProfileUnitTests PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +endif() diff --git a/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp b/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp new file mode 100644 index 000000000000..44f37d257632 --- /dev/null +++ b/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp @@ -0,0 +1,22 @@ +#include "../CtxInstrProfiling.h" +#include "gtest/gtest.h" + +using namespace __ctx_profile; + +TEST(ArenaTest, Basic) { + Arena *A = Arena::allocateNewArena(1024); + EXPECT_EQ(A->size(), 1024U); + EXPECT_EQ(A->next(), nullptr); + + auto *M1 = A->tryBumpAllocate(1020); + EXPECT_NE(M1, nullptr); + auto *M2 = A->tryBumpAllocate(4); + EXPECT_NE(M2, nullptr); + EXPECT_EQ(M1 + 1020, M2); + EXPECT_EQ(A->tryBumpAllocate(1), nullptr); + Arena *A2 = Arena::allocateNewArena(2024, A); + EXPECT_EQ(A->next(), A2); + EXPECT_EQ(A2->next(), nullptr); + Arena::freeArenaList(A); + EXPECT_EQ(A, nullptr); +} diff --git a/compiler-rt/lib/ctx_profile/tests/driver.cpp b/compiler-rt/lib/ctx_profile/tests/driver.cpp new file mode 100644 index 000000000000..b402cec1126b --- /dev/null +++ b/compiler-rt/lib/ctx_profile/tests/driver.cpp @@ -0,0 +1,14 @@ +//===-- driver.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 "gtest/gtest.h" + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- GitLab From 0ab0c1d982876662a45adb9bafaa3c2d3bdf1939 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 22 Apr 2024 12:31:57 -0400 Subject: [PATCH 186/357] [SLP]Introduce transformNodes() and transform loads + reverse to strided loads. Introduced transformNodes() function to perform transformation of the nodes (cost-based, instruction count based, etc.). Implemented transformation of consecutive loads + reverse order to strided loads with stride -1, if profitable. Reviewers: RKSimon, preames, topperc Reviewed By: RKSimon Pull Request: https://github.com/llvm/llvm-project/pull/88530 --- .../Transforms/Vectorize/SLPVectorizer.cpp | 43 +++++++++++++++++++ .../RISCV/strided-loads-vectorized.ll | 5 +-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 685a5907d94f..6ac380a6ab6c 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -1126,6 +1126,9 @@ public: void buildExternalUses(const ExtraValueToDebugLocsMap &ExternallyUsedValues = {}); + /// Transforms graph nodes to target specific representations, if profitable. + void transformNodes(); + /// Clear the internal data structures that are created by 'buildTree'. void deleteTree() { VectorizableTree.clear(); @@ -7813,6 +7816,43 @@ getGEPCosts(const TargetTransformInfo &TTI, ArrayRef Ptrs, return std::make_pair(ScalarCost, VecCost); } +void BoUpSLP::transformNodes() { + constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; + for (std::unique_ptr &TE : VectorizableTree) { + TreeEntry &E = *TE.get(); + switch (E.getOpcode()) { + case Instruction::Load: { + Type *ScalarTy = E.getMainOp()->getType(); + auto *VecTy = FixedVectorType::get(ScalarTy, E.Scalars.size()); + Align CommonAlignment = computeCommonAlignment(E.Scalars); + // Check if profitable to represent consecutive load + reverse as strided + // load with stride -1. + if (isReverseOrder(E.ReorderIndices) && + TTI->isLegalStridedLoadStore(VecTy, CommonAlignment)) { + SmallVector Mask; + inversePermutation(E.ReorderIndices, Mask); + auto *BaseLI = cast(E.Scalars.back()); + InstructionCost OriginalVecCost = + TTI->getMemoryOpCost(Instruction::Load, VecTy, BaseLI->getAlign(), + BaseLI->getPointerAddressSpace(), CostKind, + TTI::OperandValueInfo()) + + ::getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, Mask, CostKind); + InstructionCost StridedCost = TTI->getStridedMemoryOpCost( + Instruction::Load, VecTy, BaseLI->getPointerOperand(), + /*VariableMask=*/false, CommonAlignment, CostKind, BaseLI); + if (StridedCost < OriginalVecCost) + // Strided load is more profitable than consecutive load + reverse - + // transform the node to strided load. + E.State = TreeEntry::StridedVectorize; + } + break; + } + default: + break; + } + } +} + /// Merges shuffle masks and emits final shuffle instruction, if required. It /// supports shuffling of 2 input vectors. It implements lazy shuffles emission, /// when the actual shuffle instruction is generated only if this is actually @@ -15189,6 +15229,7 @@ bool SLPVectorizerPass::vectorizeStoreChain(ArrayRef Chain, BoUpSLP &R, R.buildExternalUses(); R.computeMinimumValueSizes(); + R.transformNodes(); InstructionCost Cost = R.getTreeCost(); @@ -15567,6 +15608,7 @@ bool SLPVectorizerPass::tryToVectorizeList(ArrayRef VL, BoUpSLP &R, R.buildExternalUses(); R.computeMinimumValueSizes(); + R.transformNodes(); InstructionCost Cost = R.getTreeCost(); CandidateFound = true; MinCost = std::min(MinCost, Cost); @@ -16563,6 +16605,7 @@ public: V.buildExternalUses(LocalExternallyUsedValues); V.computeMinimumValueSizes(); + V.transformNodes(); // Estimate cost. InstructionCost TreeCost = V.getTreeCost(VL); diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/strided-loads-vectorized.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/strided-loads-vectorized.ll index 03acc0009fb0..44d320c75fed 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/strided-loads-vectorized.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/strided-loads-vectorized.ll @@ -240,11 +240,10 @@ define void @test3(ptr %p, ptr noalias %s) { ; CHECK-LABEL: @test3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [48 x float], ptr [[P:%.*]], i64 0, i64 0 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [48 x float], ptr [[P]], i64 0, i64 30 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, ptr [[S:%.*]], i64 0 -; CHECK-NEXT: [[ARRAYIDX48:%.*]] = getelementptr inbounds [48 x float], ptr [[P]], i64 0, i64 23 ; CHECK-NEXT: [[TMP0:%.*]] = call <8 x float> @llvm.experimental.vp.strided.load.v8f32.p0.i64(ptr align 4 [[ARRAYIDX]], i64 16, <8 x i1> , i32 8) -; CHECK-NEXT: [[TMP1:%.*]] = load <8 x float>, ptr [[ARRAYIDX48]], align 4 -; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x float> [[TMP1]], <8 x float> poison, <8 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = call <8 x float> @llvm.experimental.vp.strided.load.v8f32.p0.i64(ptr align 4 [[ARRAYIDX1]], i64 -4, <8 x i1> , i32 8) ; CHECK-NEXT: [[TMP3:%.*]] = fsub fast <8 x float> [[TMP2]], [[TMP0]] ; CHECK-NEXT: store <8 x float> [[TMP3]], ptr [[ARRAYIDX2]], align 4 ; CHECK-NEXT: ret void -- GitLab From 832d3a42c34eee2a6ca323ef97a1c6fe14c1f651 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 22 Apr 2024 17:18:43 +0100 Subject: [PATCH 187/357] [X86] gfni-funnel-shifts.ll - add vXi8 variable/splat/constant test coverage Once #89115 has landed, we can handle per-element rotates as well using (V)GF2P8MULB --- llvm/test/CodeGen/X86/gfni-funnel-shifts.ll | 2686 ++++++++++++++++++- 1 file changed, 2684 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll b/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll index a98983e44d3d..0c341dc63a9e 100644 --- a/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll +++ b/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll @@ -9,6 +9,486 @@ ; 128 Bit Vector Funnel Shifts ; +define <16 x i8> @var_fshl_v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %amt) nounwind { +; GFNISSE-LABEL: var_fshl_v16i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; GFNISSE-NEXT: pxor %xmm3, %xmm3 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm4 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm3[8],xmm2[9],xmm3[9],xmm2[10],xmm3[10],xmm2[11],xmm3[11],xmm2[12],xmm3[12],xmm2[13],xmm3[13],xmm2[14],xmm3[14],xmm2[15],xmm3[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm2 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm6 = [1065353216,1065353216,1065353216,1065353216] +; GFNISSE-NEXT: paddd %xmm6, %xmm2 +; GFNISSE-NEXT: cvttps2dq %xmm2, %xmm2 +; GFNISSE-NEXT: pslld $23, %xmm3 +; GFNISSE-NEXT: paddd %xmm6, %xmm3 +; GFNISSE-NEXT: cvttps2dq %xmm3, %xmm3 +; GFNISSE-NEXT: packusdw %xmm2, %xmm3 +; GFNISSE-NEXT: movdqa %xmm1, %xmm7 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] +; GFNISSE-NEXT: pmullw %xmm3, %xmm7 +; GFNISSE-NEXT: psrlw $8, %xmm7 +; GFNISSE-NEXT: pslld $23, %xmm4 +; GFNISSE-NEXT: paddd %xmm6, %xmm4 +; GFNISSE-NEXT: cvttps2dq %xmm4, %xmm2 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm5 +; GFNISSE-NEXT: paddd %xmm6, %xmm5 +; GFNISSE-NEXT: cvttps2dq %xmm5, %xmm3 +; GFNISSE-NEXT: packusdw %xmm3, %xmm2 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNISSE-NEXT: pmullw %xmm1, %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: packuswb %xmm7, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: var_fshl_v16i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm2[8],xmm3[8],xmm2[9],xmm3[9],xmm2[10],xmm3[10],xmm2[11],xmm3[11],xmm2[12],xmm3[12],xmm2[13],xmm3[13],xmm2[14],xmm3[14],xmm2[15],xmm3[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm4 = xmm3[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm5 = [1065353216,1065353216,1065353216,1065353216] +; GFNIAVX1-NEXT: vpaddd %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vcvttps2dq %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpaddd %xmm5, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vcvttps2dq %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpackusdw %xmm4, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm3, %xmm4, %xmm3 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm4 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpaddd %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vcvttps2dq %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm2 = xmm2[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpaddd %xmm5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vcvttps2dq %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackusdw %xmm2, %xmm4, %xmm2 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: var_fshl_v16i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX2-NEXT: vpmovzxwd {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm2[8],xmm4[8],xmm2[9],xmm4[9],xmm2[10],xmm4[10],xmm2[11],xmm4[11],xmm2[12],xmm4[12],xmm2[13],xmm4[13],xmm2[14],xmm4[14],xmm2[15],xmm4[15] +; GFNIAVX2-NEXT: vpmovzxwd {{.*#+}} ymm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; GFNIAVX2-NEXT: vpsllvd %ymm4, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vmovdqa {{.*#+}} ymm4 = [0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15,16,17,20,21,24,25,28,29,24,25,28,29,28,29,30,31] +; GFNIAVX2-NEXT: vpshufb %ymm4, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,2,2,3] +; GFNIAVX2-NEXT: vpsrlw $8, %xmm3, %xmm3 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; GFNIAVX2-NEXT: vpmovzxbd {{.*#+}} ymm1 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero,xmm2[4],zero,zero,zero,xmm2[5],zero,zero,zero,xmm2[6],zero,zero,zero,xmm2[7],zero,zero,zero +; GFNIAVX2-NEXT: vpsllvd %ymm1, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpshufb %ymm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,2,3] +; GFNIAVX2-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vzeroupper +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: var_fshl_v16i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} xmm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX512VL-NEXT: vpand %xmm3, %xmm2, %xmm4 +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm4 = xmm4[0],zero,zero,zero,xmm4[1],zero,zero,zero,xmm4[2],zero,zero,zero,xmm4[3],zero,zero,zero,xmm4[4],zero,zero,zero,xmm4[5],zero,zero,zero,xmm4[6],zero,zero,zero,xmm4[7],zero,zero,zero,xmm4[8],zero,zero,zero,xmm4[9],zero,zero,zero,xmm4[10],zero,zero,zero,xmm4[11],zero,zero,zero,xmm4[12],zero,zero,zero,xmm4[13],zero,zero,zero,xmm4[14],zero,zero,zero,xmm4[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero,xmm0[8],zero,zero,zero,xmm0[9],zero,zero,zero,xmm0[10],zero,zero,zero,xmm0[11],zero,zero,zero,xmm0[12],zero,zero,zero,xmm0[13],zero,zero,zero,xmm0[14],zero,zero,zero,xmm0[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpsllvd %zmm4, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: vpandn %xmm3, %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm2 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero,xmm2[4],zero,zero,zero,xmm2[5],zero,zero,zero,xmm2[6],zero,zero,zero,xmm2[7],zero,zero,zero,xmm2[8],zero,zero,zero,xmm2[9],zero,zero,zero,xmm2[10],zero,zero,zero,xmm2[11],zero,zero,zero,xmm2[12],zero,zero,zero,xmm2[13],zero,zero,zero,xmm2[14],zero,zero,zero,xmm2[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpsrlw $1, %xmm1, %xmm1 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm1, %xmm1 +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm1 = xmm1[0],zero,zero,zero,xmm1[1],zero,zero,zero,xmm1[2],zero,zero,zero,xmm1[3],zero,zero,zero,xmm1[4],zero,zero,zero,xmm1[5],zero,zero,zero,xmm1[6],zero,zero,zero,xmm1[7],zero,zero,zero,xmm1[8],zero,zero,zero,xmm1[9],zero,zero,zero,xmm1[10],zero,zero,zero,xmm1[11],zero,zero,zero,xmm1[12],zero,zero,zero,xmm1[13],zero,zero,zero,xmm1[14],zero,zero,zero,xmm1[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpsrlvd %zmm2, %zmm1, %zmm1 +; GFNIAVX512VL-NEXT: vpord %zmm1, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: vpmovdb %zmm0, %xmm0 +; GFNIAVX512VL-NEXT: vzeroupper +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: var_fshl_v16i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm2, %xmm1 +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; GFNIAVX512BW-NEXT: vpsllvw %ymm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpmovwb %ymm0, %xmm0 +; GFNIAVX512BW-NEXT: vzeroupper +; GFNIAVX512BW-NEXT: retq + %res = call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %amt) + ret <16 x i8> %res +} + +define <16 x i8> @var_fshr_v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %amt) nounwind { +; GFNISSE-LABEL: var_fshr_v16i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm2, %xmm3 +; GFNISSE-NEXT: movdqa %xmm0, %xmm2 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm5 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: pand %xmm5, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: movdqa %xmm0, %xmm4 +; GFNISSE-NEXT: paddb %xmm0, %xmm4 +; GFNISSE-NEXT: movdqa %xmm1, %xmm6 +; GFNISSE-NEXT: psrlw $4, %xmm6 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm6 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm6, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm6 +; GFNISSE-NEXT: psrlw $2, %xmm6 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm6 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm6, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm6 +; GFNISSE-NEXT: psrlw $1, %xmm6 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm6 +; GFNISSE-NEXT: paddb %xmm4, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm6, %xmm1 +; GFNISSE-NEXT: pandn %xmm5, %xmm3 +; GFNISSE-NEXT: psllw $5, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm4 +; GFNISSE-NEXT: paddb %xmm3, %xmm4 +; GFNISSE-NEXT: paddb %xmm2, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm5 +; GFNISSE-NEXT: psllw $4, %xmm5 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm5 +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm5, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm3 +; GFNISSE-NEXT: psllw $2, %xmm3 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm3 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm3, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm3 +; GFNISSE-NEXT: paddb %xmm2, %xmm3 +; GFNISSE-NEXT: paddb %xmm4, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm3, %xmm2 +; GFNISSE-NEXT: por %xmm1, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: var_fshr_v16i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX1-NEXT: vpand %xmm3, %xmm2, %xmm4 +; GFNIAVX1-NEXT: vpsllw $5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm4, %xmm4, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm1, %xmm6 +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpblendvb %xmm4, %xmm6, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm5, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpandn %xmm3, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsllw $5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpaddb %xmm2, %xmm2, %xmm3 +; GFNIAVX1-NEXT: vpaddb %xmm0, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsllw $4, %xmm0, %xmm4 +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsllw $2, %xmm0, %xmm2 +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm3, %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpaddb %xmm0, %xmm0, %xmm2 +; GFNIAVX1-NEXT: vpaddb %xmm3, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpblendvb %xmm3, %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpor %xmm1, %xmm0, %xmm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: var_fshr_v16i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} xmm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 +; GFNIAVX2-NEXT: vpsllw $5, %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpaddb %xmm4, %xmm4, %xmm5 +; GFNIAVX2-NEXT: vpsrlw $4, %xmm1, %xmm6 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm6, %xmm6 +; GFNIAVX2-NEXT: vpblendvb %xmm4, %xmm6, %xmm1, %xmm1 +; GFNIAVX2-NEXT: vpsrlw $2, %xmm1, %xmm4 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpblendvb %xmm5, %xmm4, %xmm1, %xmm1 +; GFNIAVX2-NEXT: vpsrlw $1, %xmm1, %xmm4 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpaddb %xmm5, %xmm5, %xmm5 +; GFNIAVX2-NEXT: vpblendvb %xmm5, %xmm4, %xmm1, %xmm1 +; GFNIAVX2-NEXT: vpandn %xmm3, %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpsllw $5, %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpaddb %xmm2, %xmm2, %xmm3 +; GFNIAVX2-NEXT: vpaddb %xmm0, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpsllw $4, %xmm0, %xmm4 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpblendvb %xmm2, %xmm4, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpsllw $2, %xmm0, %xmm2 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpblendvb %xmm3, %xmm2, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpaddb %xmm0, %xmm0, %xmm2 +; GFNIAVX2-NEXT: vpaddb %xmm3, %xmm3, %xmm3 +; GFNIAVX2-NEXT: vpblendvb %xmm3, %xmm2, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpor %xmm1, %xmm0, %xmm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: var_fshr_v16i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} xmm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX512VL-NEXT: vpand %xmm3, %xmm2, %xmm4 +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm4 = xmm4[0],zero,zero,zero,xmm4[1],zero,zero,zero,xmm4[2],zero,zero,zero,xmm4[3],zero,zero,zero,xmm4[4],zero,zero,zero,xmm4[5],zero,zero,zero,xmm4[6],zero,zero,zero,xmm4[7],zero,zero,zero,xmm4[8],zero,zero,zero,xmm4[9],zero,zero,zero,xmm4[10],zero,zero,zero,xmm4[11],zero,zero,zero,xmm4[12],zero,zero,zero,xmm4[13],zero,zero,zero,xmm4[14],zero,zero,zero,xmm4[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm1 = xmm1[0],zero,zero,zero,xmm1[1],zero,zero,zero,xmm1[2],zero,zero,zero,xmm1[3],zero,zero,zero,xmm1[4],zero,zero,zero,xmm1[5],zero,zero,zero,xmm1[6],zero,zero,zero,xmm1[7],zero,zero,zero,xmm1[8],zero,zero,zero,xmm1[9],zero,zero,zero,xmm1[10],zero,zero,zero,xmm1[11],zero,zero,zero,xmm1[12],zero,zero,zero,xmm1[13],zero,zero,zero,xmm1[14],zero,zero,zero,xmm1[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpsrlvd %zmm4, %zmm1, %zmm1 +; GFNIAVX512VL-NEXT: vpandn %xmm3, %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm2 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero,xmm2[4],zero,zero,zero,xmm2[5],zero,zero,zero,xmm2[6],zero,zero,zero,xmm2[7],zero,zero,zero,xmm2[8],zero,zero,zero,xmm2[9],zero,zero,zero,xmm2[10],zero,zero,zero,xmm2[11],zero,zero,zero,xmm2[12],zero,zero,zero,xmm2[13],zero,zero,zero,xmm2[14],zero,zero,zero,xmm2[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpaddb %xmm0, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpmovzxbd {{.*#+}} zmm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero,xmm0[8],zero,zero,zero,xmm0[9],zero,zero,zero,xmm0[10],zero,zero,zero,xmm0[11],zero,zero,zero,xmm0[12],zero,zero,zero,xmm0[13],zero,zero,zero,xmm0[14],zero,zero,zero,xmm0[15],zero,zero,zero +; GFNIAVX512VL-NEXT: vpsllvd %zmm2, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: vpord %zmm1, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: vpmovdb %zmm0, %xmm0 +; GFNIAVX512VL-NEXT: vzeroupper +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: var_fshr_v16i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm2, %xmm1 +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; GFNIAVX512BW-NEXT: vpsrlvw %ymm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpmovwb %ymm0, %xmm0 +; GFNIAVX512BW-NEXT: vzeroupper +; GFNIAVX512BW-NEXT: retq + %res = call <16 x i8> @llvm.fshr.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %amt) + ret <16 x i8> %res +} + +define <16 x i8> @splatvar_fshl_v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %amt) nounwind { +; GFNISSE-LABEL: splatvar_fshl_v16i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm1, %xmm3 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; GFNISSE-NEXT: psllw %xmm2, %xmm3 +; GFNISSE-NEXT: psrlw $8, %xmm3 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNISSE-NEXT: psllw %xmm2, %xmm1 +; GFNISSE-NEXT: psrlw $8, %xmm1 +; GFNISSE-NEXT: packuswb %xmm3, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX-LABEL: splatvar_fshl_v16i8: +; GFNIAVX: # %bb.0: +; GFNIAVX-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX-NEXT: vpsllw %xmm2, %xmm3, %xmm3 +; GFNIAVX-NEXT: vpsrlw $8, %xmm3, %xmm3 +; GFNIAVX-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX-NEXT: vpsllw %xmm2, %xmm0, %xmm0 +; GFNIAVX-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; GFNIAVX-NEXT: retq + %splat = shufflevector <16 x i8> %amt, <16 x i8> undef, <16 x i32> zeroinitializer + %res = call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %splat) + ret <16 x i8> %res +} + +define <16 x i8> @splatvar_fshr_v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %amt) nounwind { +; GFNISSE-LABEL: splatvar_fshr_v16i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm1, %xmm4 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; GFNISSE-NEXT: psrlw %xmm2, %xmm4 +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; GFNISSE-NEXT: pand %xmm3, %xmm4 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNISSE-NEXT: psrlw %xmm2, %xmm1 +; GFNISSE-NEXT: pand %xmm1, %xmm3 +; GFNISSE-NEXT: packuswb %xmm4, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: splatvar_fshr_v16i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw %xmm2, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; GFNIAVX1-NEXT: vpand %xmm4, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpsrlw %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: splatvar_fshr_v16i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpsrlw %xmm2, %xmm3, %xmm3 +; GFNIAVX2-NEXT: vpbroadcastw {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; GFNIAVX2-NEXT: vpand %xmm4, %xmm3, %xmm3 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX2-NEXT: vpsrlw %xmm2, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpand %xmm4, %xmm0, %xmm0 +; GFNIAVX2-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: splatvar_fshr_v16i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX512VL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %xmm3, %xmm3 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; GFNIAVX512VL-NEXT: vpand %xmm4, %xmm3, %xmm3 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpand %xmm4, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: splatvar_fshr_v16i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX512BW-NEXT: vinserti128 $1, %xmm3, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm1 +; GFNIAVX512BW-NEXT: vpsrlw %xmm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpmovwb %ymm0, %xmm0 +; GFNIAVX512BW-NEXT: vzeroupper +; GFNIAVX512BW-NEXT: retq + %splat = shufflevector <16 x i8> %amt, <16 x i8> undef, <16 x i32> zeroinitializer + %res = call <16 x i8> @llvm.fshr.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %splat) + ret <16 x i8> %res +} + +define <16 x i8> @constant_fshl_v16i8(<16 x i8> %a, <16 x i8> %b) nounwind { +; GFNISSE-LABEL: constant_fshl_v16i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm1, %xmm2 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNISSE-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNISSE-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; GFNISSE-NEXT: psrlw $8, %xmm1 +; GFNISSE-NEXT: packuswb %xmm2, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX1OR2-LABEL: constant_fshl_v16i8: +; GFNIAVX1OR2: # %bb.0: +; GFNIAVX1OR2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1OR2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1OR2-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1OR2-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1OR2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; GFNIAVX1OR2-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1OR2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; GFNIAVX1OR2-NEXT: retq +; +; GFNIAVX512VL-LABEL: constant_fshl_v16i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: constant_fshl_v16i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpmovwb %ymm0, %xmm0 +; GFNIAVX512BW-NEXT: vzeroupper +; GFNIAVX512BW-NEXT: retq + %res = call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> ) + ret <16 x i8> %res +} + +define <16 x i8> @constant_fshr_v16i8(<16 x i8> %a, <16 x i8> %b) nounwind { +; GFNISSE-LABEL: constant_fshr_v16i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm1, %xmm2 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNISSE-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNISSE-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; GFNISSE-NEXT: psrlw $8, %xmm1 +; GFNISSE-NEXT: packuswb %xmm2, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX1OR2-LABEL: constant_fshr_v16i8: +; GFNIAVX1OR2: # %bb.0: +; GFNIAVX1OR2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1OR2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1OR2-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1OR2-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1OR2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; GFNIAVX1OR2-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1OR2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; GFNIAVX1OR2-NEXT: retq +; +; GFNIAVX512VL-LABEL: constant_fshr_v16i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: constant_fshr_v16i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpmovwb %ymm0, %xmm0 +; GFNIAVX512BW-NEXT: vzeroupper +; GFNIAVX512BW-NEXT: retq + %res = call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> ) + ret <16 x i8> %res +} + define <16 x i8> @splatconstant_fshl_v16i8(<16 x i8> %a, <16 x i8> %b) nounwind { ; GFNISSE-LABEL: splatconstant_fshl_v16i8: ; GFNISSE: # %bb.0: @@ -71,6 +551,788 @@ declare <16 x i8> @llvm.fshr.v16i8(<16 x i8>, <16 x i8>, <16 x i8>) ; 256 Bit Vector Funnel Shifts ; +define <32 x i8> @var_fshl_v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) nounwind { +; GFNISSE-LABEL: var_fshl_v32i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm0, %xmm6 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm8 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNISSE-NEXT: pand %xmm8, %xmm4 +; GFNISSE-NEXT: pxor %xmm7, %xmm7 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm0 = xmm4[0],zero,zero,zero,xmm4[1],zero,zero,zero,xmm4[2],zero,zero,zero,xmm4[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; GFNISSE-NEXT: movdqa %xmm4, %xmm10 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm7[8],xmm10[9],xmm7[9],xmm10[10],xmm7[10],xmm10[11],xmm7[11],xmm10[12],xmm7[12],xmm10[13],xmm7[13],xmm10[14],xmm7[14],xmm10[15],xmm7[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm11 = xmm10[0],zero,xmm10[1],zero,xmm10[2],zero,xmm10[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm10 = xmm10[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm10 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm4 = [1065353216,1065353216,1065353216,1065353216] +; GFNISSE-NEXT: paddd %xmm4, %xmm10 +; GFNISSE-NEXT: cvttps2dq %xmm10, %xmm10 +; GFNISSE-NEXT: pslld $23, %xmm11 +; GFNISSE-NEXT: paddd %xmm4, %xmm11 +; GFNISSE-NEXT: cvttps2dq %xmm11, %xmm11 +; GFNISSE-NEXT: packusdw %xmm10, %xmm11 +; GFNISSE-NEXT: movdqa %xmm2, %xmm10 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm6[8],xmm10[9],xmm6[9],xmm10[10],xmm6[10],xmm10[11],xmm6[11],xmm10[12],xmm6[12],xmm10[13],xmm6[13],xmm10[14],xmm6[14],xmm10[15],xmm6[15] +; GFNISSE-NEXT: pmullw %xmm11, %xmm10 +; GFNISSE-NEXT: psrlw $8, %xmm10 +; GFNISSE-NEXT: pslld $23, %xmm0 +; GFNISSE-NEXT: paddd %xmm4, %xmm0 +; GFNISSE-NEXT: cvttps2dq %xmm0, %xmm0 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm9 = xmm9[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm9 +; GFNISSE-NEXT: paddd %xmm4, %xmm9 +; GFNISSE-NEXT: cvttps2dq %xmm9, %xmm9 +; GFNISSE-NEXT: packusdw %xmm9, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1],xmm2[2],xmm6[2],xmm2[3],xmm6[3],xmm2[4],xmm6[4],xmm2[5],xmm6[5],xmm2[6],xmm6[6],xmm2[7],xmm6[7] +; GFNISSE-NEXT: pmullw %xmm2, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: packuswb %xmm10, %xmm0 +; GFNISSE-NEXT: pand %xmm8, %xmm5 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm2 = xmm5[0],zero,zero,zero,xmm5[1],zero,zero,zero,xmm5[2],zero,zero,zero,xmm5[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm7[8],xmm5[9],xmm7[9],xmm5[10],xmm7[10],xmm5[11],xmm7[11],xmm5[12],xmm7[12],xmm5[13],xmm7[13],xmm5[14],xmm7[14],xmm5[15],xmm7[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm7 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm5 +; GFNISSE-NEXT: paddd %xmm4, %xmm5 +; GFNISSE-NEXT: cvttps2dq %xmm5, %xmm5 +; GFNISSE-NEXT: pslld $23, %xmm7 +; GFNISSE-NEXT: paddd %xmm4, %xmm7 +; GFNISSE-NEXT: cvttps2dq %xmm7, %xmm7 +; GFNISSE-NEXT: packusdw %xmm5, %xmm7 +; GFNISSE-NEXT: movdqa %xmm3, %xmm5 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm1[8],xmm5[9],xmm1[9],xmm5[10],xmm1[10],xmm5[11],xmm1[11],xmm5[12],xmm1[12],xmm5[13],xmm1[13],xmm5[14],xmm1[14],xmm5[15],xmm1[15] +; GFNISSE-NEXT: pmullw %xmm7, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: pslld $23, %xmm2 +; GFNISSE-NEXT: paddd %xmm4, %xmm2 +; GFNISSE-NEXT: cvttps2dq %xmm2, %xmm2 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm6 = xmm6[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm6 +; GFNISSE-NEXT: paddd %xmm4, %xmm6 +; GFNISSE-NEXT: cvttps2dq %xmm6, %xmm4 +; GFNISSE-NEXT: packusdw %xmm4, %xmm2 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNISSE-NEXT: pmullw %xmm3, %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: packuswb %xmm5, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm1 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: var_fshl_v32i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm4 +; GFNIAVX1-NEXT: vpxor %xmm5, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm3 = xmm6[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm3, %xmm7 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [1065353216,1065353216,1065353216,1065353216] +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vcvttps2dq %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vcvttps2dq %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpackusdw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm7 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm8 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm8[8],xmm7[8],xmm8[9],xmm7[9],xmm8[10],xmm7[10],xmm8[11],xmm7[11],xmm8[12],xmm7[12],xmm8[13],xmm7[13],xmm8[14],xmm7[14],xmm8[15],xmm7[15] +; GFNIAVX1-NEXT: vpmullw %xmm6, %xmm9, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm9 = xmm4[0],zero,zero,zero,xmm4[1],zero,zero,zero,xmm4[2],zero,zero,zero,xmm4[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vcvttps2dq %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm4 = xmm4[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vcvttps2dq %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpackusdw %xmm4, %xmm9, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm8[0],xmm7[0],xmm8[1],xmm7[1],xmm8[2],xmm7[2],xmm8[3],xmm7[3],xmm8[4],xmm7[4],xmm8[5],xmm7[5],xmm8[6],xmm7[6],xmm8[7],xmm7[7] +; GFNIAVX1-NEXT: vpmullw %xmm4, %xmm7, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm2[8],xmm5[8],xmm2[9],xmm5[9],xmm2[10],xmm5[10],xmm2[11],xmm5[11],xmm2[12],xmm5[12],xmm2[13],xmm5[13],xmm2[14],xmm5[14],xmm2[15],xmm5[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm6 = xmm5[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vcvttps2dq %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vcvttps2dq %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpackusdw %xmm6, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm6, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm6 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vcvttps2dq %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm2 = xmm2[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpaddd %xmm3, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vcvttps2dq %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackusdw %xmm2, %xmm6, %xmm2 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm5, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: var_fshl_v32i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX2-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm5 = ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[12],ymm3[12],ymm4[13],ymm3[13],ymm4[14],ymm3[14],ymm4[15],ymm3[15] +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm6 = ymm2[8],ymm4[8],ymm2[9],ymm4[9],ymm2[10],ymm4[10],ymm2[11],ymm4[11],ymm2[12],ymm4[12],ymm2[13],ymm4[13],ymm2[14],ymm4[14],ymm2[15],ymm4[15],ymm2[24],ymm4[24],ymm2[25],ymm4[25],ymm2[26],ymm4[26],ymm2[27],ymm4[27],ymm2[28],ymm4[28],ymm2[29],ymm4[29],ymm2[30],ymm4[30],ymm2[31],ymm4[31] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm7 = ymm6[4],ymm4[4],ymm6[5],ymm4[5],ymm6[6],ymm4[6],ymm6[7],ymm4[7],ymm6[12],ymm4[12],ymm6[13],ymm4[13],ymm6[14],ymm4[14],ymm6[15],ymm4[15] +; GFNIAVX2-NEXT: vpsllvd %ymm7, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpsrld $16, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[8],ymm3[8],ymm4[9],ymm3[9],ymm4[10],ymm3[10],ymm4[11],ymm3[11] +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm6 = ymm6[0],ymm4[0],ymm6[1],ymm4[1],ymm6[2],ymm4[2],ymm6[3],ymm4[3],ymm6[8],ymm4[8],ymm6[9],ymm4[9],ymm6[10],ymm4[10],ymm6[11],ymm4[11] +; GFNIAVX2-NEXT: vpsllvd %ymm6, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpsrld $16, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpackusdw %ymm5, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm1 = ymm4[4],ymm0[4],ymm4[5],ymm0[5],ymm4[6],ymm0[6],ymm4[7],ymm0[7],ymm4[12],ymm0[12],ymm4[13],ymm0[13],ymm4[14],ymm0[14],ymm4[15],ymm0[15] +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm5 = ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[12],ymm4[12],ymm2[13],ymm4[13],ymm2[14],ymm4[14],ymm2[15],ymm4[15] +; GFNIAVX2-NEXT: vpsllvd %ymm5, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrld $16, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm0 = ymm4[0],ymm0[0],ymm4[1],ymm0[1],ymm4[2],ymm0[2],ymm4[3],ymm0[3],ymm4[8],ymm0[8],ymm4[9],ymm0[9],ymm4[10],ymm0[10],ymm4[11],ymm0[11] +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm2 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[8],ymm4[8],ymm2[9],ymm4[9],ymm2[10],ymm4[10],ymm2[11],ymm4[11] +; GFNIAVX2-NEXT: vpsllvd %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrld $16, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackusdw %ymm1, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: var_fshl_v32i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX512VL-NEXT: vpandn %ymm3, %ymm2, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm5 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $4, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm6, %ymm6 +; GFNIAVX512VL-NEXT: vpblendvb %ymm4, %ymm6, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $2, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm6, %ymm6 +; GFNIAVX512VL-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpblendvb %ymm4, %ymm6, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm6, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpblendvb %ymm4, %ymm5, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpand %ymm3, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpaddb %ymm2, %ymm2, %ymm3 +; GFNIAVX512VL-NEXT: vpsllw $4, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsllw $2, %ymm0, %ymm2 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpaddb %ymm0, %ymm0, %ymm2 +; GFNIAVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: var_fshl_v32i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero,ymm0[16],zero,ymm0[17],zero,ymm0[18],zero,ymm0[19],zero,ymm0[20],zero,ymm0[21],zero,ymm0[22],zero,ymm0[23],zero,ymm0[24],zero,ymm0[25],zero,ymm0[26],zero,ymm0[27],zero,ymm0[28],zero,ymm0[29],zero,ymm0[30],zero,ymm0[31],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vporq %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm2, %ymm1 +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; GFNIAVX512BW-NEXT: vpsllvw %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpmovwb %zmm0, %ymm0 +; GFNIAVX512BW-NEXT: retq + %res = call <32 x i8> @llvm.fshl.v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) + ret <32 x i8> %res +} + +define <32 x i8> @var_fshr_v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) nounwind { +; GFNISSE-LABEL: var_fshr_v32i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm4, %xmm6 +; GFNISSE-NEXT: movdqa %xmm0, %xmm4 +; GFNISSE-NEXT: movdqa %xmm2, %xmm9 +; GFNISSE-NEXT: psrlw $4, %xmm9 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm8 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNISSE-NEXT: pand %xmm8, %xmm9 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm7 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: pand %xmm7, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm9, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm10 +; GFNISSE-NEXT: psrlw $2, %xmm10 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm9 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNISSE-NEXT: pand %xmm9, %xmm10 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm10, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm11 +; GFNISSE-NEXT: psrlw $1, %xmm11 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm10 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNISSE-NEXT: pand %xmm10, %xmm11 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm11, %xmm2 +; GFNISSE-NEXT: paddb %xmm4, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm12 +; GFNISSE-NEXT: psllw $4, %xmm12 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm11 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNISSE-NEXT: pand %xmm11, %xmm12 +; GFNISSE-NEXT: pandn %xmm7, %xmm6 +; GFNISSE-NEXT: psllw $5, %xmm6 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm12, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm13 +; GFNISSE-NEXT: psllw $2, %xmm13 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm12 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNISSE-NEXT: pand %xmm12, %xmm13 +; GFNISSE-NEXT: paddb %xmm6, %xmm6 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm13, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm13 +; GFNISSE-NEXT: paddb %xmm4, %xmm13 +; GFNISSE-NEXT: paddb %xmm6, %xmm6 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm13, %xmm4 +; GFNISSE-NEXT: por %xmm2, %xmm4 +; GFNISSE-NEXT: movdqa %xmm3, %xmm2 +; GFNISSE-NEXT: psrlw $4, %xmm2 +; GFNISSE-NEXT: pand %xmm8, %xmm2 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: pand %xmm7, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm2, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm2 +; GFNISSE-NEXT: psrlw $2, %xmm2 +; GFNISSE-NEXT: pand %xmm9, %xmm2 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm2, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm2 +; GFNISSE-NEXT: psrlw $1, %xmm2 +; GFNISSE-NEXT: pand %xmm10, %xmm2 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm2, %xmm3 +; GFNISSE-NEXT: paddb %xmm1, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm2 +; GFNISSE-NEXT: psllw $4, %xmm2 +; GFNISSE-NEXT: pand %xmm11, %xmm2 +; GFNISSE-NEXT: pandn %xmm7, %xmm5 +; GFNISSE-NEXT: psllw $5, %xmm5 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm2, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm2 +; GFNISSE-NEXT: psllw $2, %xmm2 +; GFNISSE-NEXT: pand %xmm12, %xmm2 +; GFNISSE-NEXT: paddb %xmm5, %xmm5 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm2, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm2 +; GFNISSE-NEXT: paddb %xmm1, %xmm2 +; GFNISSE-NEXT: paddb %xmm5, %xmm5 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm2, %xmm1 +; GFNISSE-NEXT: por %xmm3, %xmm1 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: var_fshr_v32i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm5, %xmm3 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNIAVX1-NEXT: vpand %xmm4, %xmm3, %xmm6 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} ymm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX1-NEXT: vandps %ymm3, %ymm2, %ymm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm7 +; GFNIAVX1-NEXT: vpsllw $5, %xmm7, %xmm8 +; GFNIAVX1-NEXT: vpblendvb %xmm8, %xmm6, %xmm5, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm6, %xmm9 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm5 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNIAVX1-NEXT: vpand %xmm5, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpaddb %xmm8, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpblendvb %xmm8, %xmm9, %xmm6, %xmm9 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm9, %xmm10 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm6 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNIAVX1-NEXT: vpand %xmm6, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpaddb %xmm8, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpblendvb %xmm8, %xmm10, %xmm9, %xmm8 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm9 +; GFNIAVX1-NEXT: vpaddb %xmm9, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpsllw $4, %xmm9, %xmm10 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm11 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNIAVX1-NEXT: vpand %xmm11, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpxor %xmm3, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpsllw $5, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpblendvb %xmm7, %xmm10, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpsllw $2, %xmm9, %xmm10 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm12 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNIAVX1-NEXT: vpand %xmm12, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpaddb %xmm7, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpblendvb %xmm7, %xmm10, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpaddb %xmm9, %xmm9, %xmm10 +; GFNIAVX1-NEXT: vpaddb %xmm7, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpblendvb %xmm7, %xmm10, %xmm9, %xmm7 +; GFNIAVX1-NEXT: vpor %xmm7, %xmm8, %xmm7 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm1, %xmm8 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm8, %xmm4 +; GFNIAVX1-NEXT: vpsllw $5, %xmm2, %xmm8 +; GFNIAVX1-NEXT: vpblendvb %xmm8, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm8, %xmm8, %xmm5 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm6, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm5, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpaddb %xmm0, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsllw $4, %xmm0, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm11, %xmm4 +; GFNIAVX1-NEXT: vpxor %xmm3, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsllw $5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsllw $2, %xmm0, %xmm3 +; GFNIAVX1-NEXT: vpand %xmm3, %xmm12, %xmm3 +; GFNIAVX1-NEXT: vpaddb %xmm2, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm3, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpaddb %xmm0, %xmm0, %xmm3 +; GFNIAVX1-NEXT: vpaddb %xmm2, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm3, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpor %xmm1, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm7, %ymm0, %ymm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: var_fshr_v32i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX2-NEXT: vpand %ymm3, %ymm2, %ymm4 +; GFNIAVX2-NEXT: vpsllw $5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm5 +; GFNIAVX2-NEXT: vpsrlw $4, %ymm1, %ymm6 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm6, %ymm6 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm6, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrlw $2, %ymm1, %ymm4 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm5, %ymm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrlw $1, %ymm1, %ymm4 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpaddb %ymm5, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpblendvb %ymm5, %ymm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpandn %ymm3, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsllw $5, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpaddb %ymm2, %ymm2, %ymm3 +; GFNIAVX2-NEXT: vpaddb %ymm0, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsllw $4, %ymm0, %ymm4 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsllw $2, %ymm0, %ymm2 +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpblendvb %ymm3, %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpaddb %ymm0, %ymm0, %ymm2 +; GFNIAVX2-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpblendvb %ymm3, %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: var_fshr_v32i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm3 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX512VL-NEXT: vpand %ymm3, %ymm2, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm4, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpsrlw $4, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm6, %ymm6 +; GFNIAVX512VL-NEXT: vpblendvb %ymm4, %ymm6, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $2, %ymm1, %ymm4 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpblendvb %ymm5, %ymm4, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm1, %ymm4 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm5, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpblendvb %ymm5, %ymm4, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpandn %ymm3, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpaddb %ymm2, %ymm2, %ymm3 +; GFNIAVX512VL-NEXT: vpaddb %ymm0, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsllw $4, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsllw $2, %ymm0, %ymm2 +; GFNIAVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpaddb %ymm0, %ymm0, %ymm2 +; GFNIAVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpor %ymm1, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: var_fshr_v32i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero,ymm0[16],zero,ymm0[17],zero,ymm0[18],zero,ymm0[19],zero,ymm0[20],zero,ymm0[21],zero,ymm0[22],zero,ymm0[23],zero,ymm0[24],zero,ymm0[25],zero,ymm0[26],zero,ymm0[27],zero,ymm0[28],zero,ymm0[29],zero,ymm0[30],zero,ymm0[31],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vporq %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm2, %ymm1 +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; GFNIAVX512BW-NEXT: vpsrlvw %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpmovwb %zmm0, %ymm0 +; GFNIAVX512BW-NEXT: retq + %res = call <32 x i8> @llvm.fshr.v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) + ret <32 x i8> %res +} + +define <32 x i8> @splatvar_fshl_v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) nounwind { +; GFNISSE-LABEL: splatvar_fshl_v32i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm2, %xmm5 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4 +; GFNISSE-NEXT: psllw %xmm4, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNISSE-NEXT: psllw %xmm4, %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: packuswb %xmm5, %xmm2 +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: psllw %xmm4, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNISSE-NEXT: psllw %xmm4, %xmm3 +; GFNISSE-NEXT: psrlw $8, %xmm3 +; GFNISSE-NEXT: packuswb %xmm0, %xmm3 +; GFNISSE-NEXT: movdqa %xmm2, %xmm0 +; GFNISSE-NEXT: movdqa %xmm3, %xmm1 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: splatvar_fshl_v32i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsllw %xmm2, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3],xmm4[4],xmm3[4],xmm4[5],xmm3[5],xmm4[6],xmm3[6],xmm4[7],xmm3[7] +; GFNIAVX1-NEXT: vpsllw %xmm2, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpackuswb %xmm5, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpsllw %xmm2, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpsllw %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm3, %ymm0, %ymm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: splatvar_fshl_v32i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpsllw %xmm2, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX2-NEXT: vpsllw %xmm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512-LABEL: splatvar_fshl_v32i8: +; GFNIAVX512: # %bb.0: +; GFNIAVX512-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512-NEXT: vpsllw %xmm2, %ymm3, %ymm3 +; GFNIAVX512-NEXT: vpsrlw $8, %ymm3, %ymm3 +; GFNIAVX512-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512-NEXT: vpsllw %xmm2, %ymm0, %ymm0 +; GFNIAVX512-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; GFNIAVX512-NEXT: retq + %splat = shufflevector <32 x i8> %amt, <32 x i8> undef, <32 x i32> zeroinitializer + %res = call <32 x i8> @llvm.fshl.v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %splat) + ret <32 x i8> %res +} + +define <32 x i8> @splatvar_fshr_v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) nounwind { +; GFNISSE-LABEL: splatvar_fshr_v32i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm2, %xmm6 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4 +; GFNISSE-NEXT: psrlw %xmm4, %xmm6 +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm5 = [255,255,255,255,255,255,255,255] +; GFNISSE-NEXT: pand %xmm5, %xmm6 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNISSE-NEXT: psrlw %xmm4, %xmm2 +; GFNISSE-NEXT: pand %xmm5, %xmm2 +; GFNISSE-NEXT: packuswb %xmm6, %xmm2 +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: psrlw %xmm4, %xmm0 +; GFNISSE-NEXT: pand %xmm5, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNISSE-NEXT: psrlw %xmm4, %xmm3 +; GFNISSE-NEXT: pand %xmm3, %xmm5 +; GFNISSE-NEXT: packuswb %xmm0, %xmm5 +; GFNISSE-NEXT: movdqa %xmm2, %xmm0 +; GFNISSE-NEXT: movdqa %xmm5, %xmm1 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: splatvar_fshr_v32i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw %xmm2, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm6 = [255,255,255,255,255,255,255,255] +; GFNIAVX1-NEXT: vpand %xmm6, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3],xmm4[4],xmm3[4],xmm4[5],xmm3[5],xmm4[6],xmm3[6],xmm4[7],xmm3[7] +; GFNIAVX1-NEXT: vpsrlw %xmm2, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpand %xmm6, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpackuswb %xmm5, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpsrlw %xmm2, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm6, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpsrlw %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpand %xmm6, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm3, %ymm0, %ymm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: splatvar_fshr_v32i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX2-NEXT: vpsrlw %xmm2, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpbroadcastw {{.*#+}} ymm4 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX2-NEXT: vpand %ymm4, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX2-NEXT: vpsrlw %xmm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpand %ymm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: splatvar_fshr_v32i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm4 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: splatvar_fshr_v32i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512BW-NEXT: vpsrlw %xmm2, %ymm3, %ymm3 +; GFNIAVX512BW-NEXT: vpbroadcastw {{.*#+}} ymm4 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX512BW-NEXT: vpand %ymm4, %ymm3, %ymm3 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512BW-NEXT: vpsrlw %xmm2, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpand %ymm4, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; GFNIAVX512BW-NEXT: retq + %splat = shufflevector <32 x i8> %amt, <32 x i8> undef, <32 x i32> zeroinitializer + %res = call <32 x i8> @llvm.fshr.v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %splat) + ret <32 x i8> %res +} + +define <32 x i8> @constant_fshl_v32i8(<32 x i8> %a, <32 x i8> %b) nounwind { +; GFNISSE-LABEL: constant_fshl_v32i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm2, %xmm5 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm6 = [1,128,64,32,16,8,4,2] +; GFNISSE-NEXT: pmullw %xmm6, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm4 = [1,2,4,8,16,32,64,128] +; GFNISSE-NEXT: pmullw %xmm4, %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: packuswb %xmm5, %xmm2 +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: pmullw %xmm6, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNISSE-NEXT: pmullw %xmm3, %xmm4 +; GFNISSE-NEXT: psrlw $8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm0, %xmm4 +; GFNISSE-NEXT: movdqa %xmm2, %xmm0 +; GFNISSE-NEXT: movdqa %xmm4, %xmm1 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: constant_fshl_v32i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm3 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm2[8],xmm3[9],xmm2[9],xmm3[10],xmm2[10],xmm3[11],xmm2[11],xmm3[12],xmm2[12],xmm3[13],xmm2[13],xmm3[14],xmm2[14],xmm3[15],xmm2[15] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = [1,128,64,32,16,8,4,2] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[1],xmm2[1],xmm3[2],xmm2[2],xmm3[3],xmm2[3],xmm3[4],xmm2[4],xmm3[5],xmm2[5],xmm3[6],xmm2[6],xmm3[7],xmm2[7] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = [1,2,4,8,16,32,64,128] +; GFNIAVX1-NEXT: vpmullw %xmm3, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm3, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: constant_fshl_v32i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: constant_fshl_v32i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: constant_fshl_v32i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero,ymm0[16],zero,ymm0[17],zero,ymm0[18],zero,ymm0[19],zero,ymm0[20],zero,ymm0[21],zero,ymm0[22],zero,ymm0[23],zero,ymm0[24],zero,ymm0[25],zero,ymm0[26],zero,ymm0[27],zero,ymm0[28],zero,ymm0[29],zero,ymm0[30],zero,ymm0[31],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vporq %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpmovwb %zmm0, %ymm0 +; GFNIAVX512BW-NEXT: retq + %res = call <32 x i8> @llvm.fshl.v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> ) + ret <32 x i8> %res +} + +define <32 x i8> @constant_fshr_v32i8(<32 x i8> %a, <32 x i8> %b) nounwind { +; GFNISSE-LABEL: constant_fshr_v32i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm2, %xmm5 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm6 = [1,128,64,32,16,8,4,2] +; GFNISSE-NEXT: pmullw %xmm6, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm4 = [1,2,4,8,16,32,64,128] +; GFNISSE-NEXT: pmullw %xmm4, %xmm2 +; GFNISSE-NEXT: psrlw $8, %xmm2 +; GFNISSE-NEXT: packuswb %xmm5, %xmm2 +; GFNISSE-NEXT: movdqa %xmm3, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: pmullw %xmm6, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNISSE-NEXT: pmullw %xmm3, %xmm4 +; GFNISSE-NEXT: psrlw $8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm0, %xmm4 +; GFNISSE-NEXT: movdqa %xmm2, %xmm0 +; GFNISSE-NEXT: movdqa %xmm4, %xmm1 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: constant_fshr_v32i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm3 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm2[8],xmm3[9],xmm2[9],xmm3[10],xmm2[10],xmm3[11],xmm2[11],xmm3[12],xmm2[12],xmm3[13],xmm2[13],xmm3[14],xmm2[14],xmm3[15],xmm2[15] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = [1,128,64,32,16,8,4,2] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[1],xmm2[1],xmm3[2],xmm2[2],xmm3[3],xmm2[3],xmm3[4],xmm2[4],xmm3[5],xmm2[5],xmm3[6],xmm2[6],xmm3[7],xmm2[7] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = [1,2,4,8,16,32,64,128] +; GFNIAVX1-NEXT: vpmullw %xmm3, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm3, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: constant_fshr_v32i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: constant_fshr_v32i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: constant_fshr_v32i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; GFNIAVX512BW-NEXT: vpmovzxbw {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero,ymm0[16],zero,ymm0[17],zero,ymm0[18],zero,ymm0[19],zero,ymm0[20],zero,ymm0[21],zero,ymm0[22],zero,ymm0[23],zero,ymm0[24],zero,ymm0[25],zero,ymm0[26],zero,ymm0[27],zero,ymm0[28],zero,ymm0[29],zero,ymm0[30],zero,ymm0[31],zero +; GFNIAVX512BW-NEXT: vpsllw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vporq %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpmovwb %zmm0, %ymm0 +; GFNIAVX512BW-NEXT: retq + %res = call <32 x i8> @llvm.fshl.v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> ) + ret <32 x i8> %res +} + define <32 x i8> @splatconstant_fshl_v32i8(<32 x i8> %a, <32 x i8> %b) nounwind { ; GFNISSE-LABEL: splatconstant_fshl_v32i8: ; GFNISSE: # %bb.0: @@ -187,6 +1449,1428 @@ declare <32 x i8> @llvm.fshr.v32i8(<32 x i8>, <32 x i8>, <32 x i8>) ; 512 Bit Vector Funnel Shifts ; +define <64 x i8> @var_fshl_v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) nounwind { +; GFNISSE-LABEL: var_fshl_v64i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm1, %xmm8 +; GFNISSE-NEXT: movdqa %xmm0, %xmm1 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm9 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm0 +; GFNISSE-NEXT: pand %xmm9, %xmm0 +; GFNISSE-NEXT: pxor %xmm10, %xmm10 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm12 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm13 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm10[8],xmm0[9],xmm10[9],xmm0[10],xmm10[10],xmm0[11],xmm10[11],xmm0[12],xmm10[12],xmm0[13],xmm10[13],xmm0[14],xmm10[14],xmm0[15],xmm10[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm14 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm0 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm11 = [1065353216,1065353216,1065353216,1065353216] +; GFNISSE-NEXT: paddd %xmm11, %xmm0 +; GFNISSE-NEXT: cvttps2dq %xmm0, %xmm0 +; GFNISSE-NEXT: pslld $23, %xmm14 +; GFNISSE-NEXT: paddd %xmm11, %xmm14 +; GFNISSE-NEXT: cvttps2dq %xmm14, %xmm14 +; GFNISSE-NEXT: packusdw %xmm0, %xmm14 +; GFNISSE-NEXT: movdqa %xmm4, %xmm15 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm15 = xmm15[8],xmm1[8],xmm15[9],xmm1[9],xmm15[10],xmm1[10],xmm15[11],xmm1[11],xmm15[12],xmm1[12],xmm15[13],xmm1[13],xmm15[14],xmm1[14],xmm15[15],xmm1[15] +; GFNISSE-NEXT: pmullw %xmm14, %xmm15 +; GFNISSE-NEXT: psrlw $8, %xmm15 +; GFNISSE-NEXT: pslld $23, %xmm12 +; GFNISSE-NEXT: paddd %xmm11, %xmm12 +; GFNISSE-NEXT: cvttps2dq %xmm12, %xmm0 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm13 = xmm13[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm13 +; GFNISSE-NEXT: paddd %xmm11, %xmm13 +; GFNISSE-NEXT: cvttps2dq %xmm13, %xmm12 +; GFNISSE-NEXT: packusdw %xmm12, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1],xmm4[2],xmm1[2],xmm4[3],xmm1[3],xmm4[4],xmm1[4],xmm4[5],xmm1[5],xmm4[6],xmm1[6],xmm4[7],xmm1[7] +; GFNISSE-NEXT: pmullw %xmm4, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: packuswb %xmm15, %xmm0 +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm1 +; GFNISSE-NEXT: pand %xmm9, %xmm1 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm4 = xmm1[0],zero,zero,zero,xmm1[1],zero,zero,zero,xmm1[2],zero,zero,zero,xmm1[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm12 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm10[8],xmm1[9],xmm10[9],xmm1[10],xmm10[10],xmm1[11],xmm10[11],xmm1[12],xmm10[12],xmm1[13],xmm10[13],xmm1[14],xmm10[14],xmm1[15],xmm10[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm13 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm1 +; GFNISSE-NEXT: paddd %xmm11, %xmm1 +; GFNISSE-NEXT: cvttps2dq %xmm1, %xmm1 +; GFNISSE-NEXT: pslld $23, %xmm13 +; GFNISSE-NEXT: paddd %xmm11, %xmm13 +; GFNISSE-NEXT: cvttps2dq %xmm13, %xmm13 +; GFNISSE-NEXT: packusdw %xmm1, %xmm13 +; GFNISSE-NEXT: movdqa %xmm5, %xmm14 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm14 = xmm14[8],xmm8[8],xmm14[9],xmm8[9],xmm14[10],xmm8[10],xmm14[11],xmm8[11],xmm14[12],xmm8[12],xmm14[13],xmm8[13],xmm14[14],xmm8[14],xmm14[15],xmm8[15] +; GFNISSE-NEXT: pmullw %xmm13, %xmm14 +; GFNISSE-NEXT: psrlw $8, %xmm14 +; GFNISSE-NEXT: pslld $23, %xmm4 +; GFNISSE-NEXT: paddd %xmm11, %xmm4 +; GFNISSE-NEXT: cvttps2dq %xmm4, %xmm1 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm12 = xmm12[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm12 +; GFNISSE-NEXT: paddd %xmm11, %xmm12 +; GFNISSE-NEXT: cvttps2dq %xmm12, %xmm4 +; GFNISSE-NEXT: packusdw %xmm4, %xmm1 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm8[0],xmm5[1],xmm8[1],xmm5[2],xmm8[2],xmm5[3],xmm8[3],xmm5[4],xmm8[4],xmm5[5],xmm8[5],xmm5[6],xmm8[6],xmm5[7],xmm8[7] +; GFNISSE-NEXT: pmullw %xmm5, %xmm1 +; GFNISSE-NEXT: psrlw $8, %xmm1 +; GFNISSE-NEXT: packuswb %xmm14, %xmm1 +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm4 +; GFNISSE-NEXT: pand %xmm9, %xmm4 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm5 = xmm4[0],zero,zero,zero,xmm4[1],zero,zero,zero,xmm4[2],zero,zero,zero,xmm4[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm8 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm12 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm4 +; GFNISSE-NEXT: paddd %xmm11, %xmm4 +; GFNISSE-NEXT: cvttps2dq %xmm4, %xmm4 +; GFNISSE-NEXT: pslld $23, %xmm12 +; GFNISSE-NEXT: paddd %xmm11, %xmm12 +; GFNISSE-NEXT: cvttps2dq %xmm12, %xmm12 +; GFNISSE-NEXT: packusdw %xmm4, %xmm12 +; GFNISSE-NEXT: movdqa %xmm6, %xmm13 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm13 = xmm13[8],xmm2[8],xmm13[9],xmm2[9],xmm13[10],xmm2[10],xmm13[11],xmm2[11],xmm13[12],xmm2[12],xmm13[13],xmm2[13],xmm13[14],xmm2[14],xmm13[15],xmm2[15] +; GFNISSE-NEXT: pmullw %xmm12, %xmm13 +; GFNISSE-NEXT: psrlw $8, %xmm13 +; GFNISSE-NEXT: pslld $23, %xmm5 +; GFNISSE-NEXT: paddd %xmm11, %xmm5 +; GFNISSE-NEXT: cvttps2dq %xmm5, %xmm4 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm8 = xmm8[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm8 +; GFNISSE-NEXT: paddd %xmm11, %xmm8 +; GFNISSE-NEXT: cvttps2dq %xmm8, %xmm5 +; GFNISSE-NEXT: packusdw %xmm5, %xmm4 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm2[0],xmm6[1],xmm2[1],xmm6[2],xmm2[2],xmm6[3],xmm2[3],xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; GFNISSE-NEXT: pmullw %xmm6, %xmm4 +; GFNISSE-NEXT: psrlw $8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm13, %xmm4 +; GFNISSE-NEXT: pand {{[0-9]+}}(%rsp), %xmm9 +; GFNISSE-NEXT: pmovzxbd {{.*#+}} xmm2 = xmm9[0],zero,zero,zero,xmm9[1],zero,zero,zero,xmm9[2],zero,zero,zero,xmm9[3],zero,zero,zero +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero,xmm9[4],zero,xmm9[5],zero,xmm9[6],zero,xmm9[7],zero +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm10[8],xmm9[9],xmm10[9],xmm9[10],xmm10[10],xmm9[11],xmm10[11],xmm9[12],xmm10[12],xmm9[13],xmm10[13],xmm9[14],xmm10[14],xmm9[15],xmm10[15] +; GFNISSE-NEXT: pmovzxwd {{.*#+}} xmm5 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm9 = xmm9[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm9 +; GFNISSE-NEXT: paddd %xmm11, %xmm9 +; GFNISSE-NEXT: cvttps2dq %xmm9, %xmm8 +; GFNISSE-NEXT: pslld $23, %xmm5 +; GFNISSE-NEXT: paddd %xmm11, %xmm5 +; GFNISSE-NEXT: cvttps2dq %xmm5, %xmm5 +; GFNISSE-NEXT: packusdw %xmm8, %xmm5 +; GFNISSE-NEXT: movdqa %xmm7, %xmm8 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm3[8],xmm8[9],xmm3[9],xmm8[10],xmm3[10],xmm8[11],xmm3[11],xmm8[12],xmm3[12],xmm8[13],xmm3[13],xmm8[14],xmm3[14],xmm8[15],xmm3[15] +; GFNISSE-NEXT: pmullw %xmm5, %xmm8 +; GFNISSE-NEXT: psrlw $8, %xmm8 +; GFNISSE-NEXT: pslld $23, %xmm2 +; GFNISSE-NEXT: paddd %xmm11, %xmm2 +; GFNISSE-NEXT: cvttps2dq %xmm2, %xmm5 +; GFNISSE-NEXT: punpckhwd {{.*#+}} xmm6 = xmm6[4,4,5,5,6,6,7,7] +; GFNISSE-NEXT: pslld $23, %xmm6 +; GFNISSE-NEXT: paddd %xmm11, %xmm6 +; GFNISSE-NEXT: cvttps2dq %xmm6, %xmm2 +; GFNISSE-NEXT: packusdw %xmm2, %xmm5 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm3[0],xmm7[1],xmm3[1],xmm7[2],xmm3[2],xmm7[3],xmm3[3],xmm7[4],xmm3[4],xmm7[5],xmm3[5],xmm7[6],xmm3[6],xmm7[7],xmm3[7] +; GFNISSE-NEXT: pmullw %xmm7, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: packuswb %xmm8, %xmm5 +; GFNISSE-NEXT: movdqa %xmm4, %xmm2 +; GFNISSE-NEXT: movdqa %xmm5, %xmm3 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: var_fshl_v64i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} ymm7 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX1-NEXT: vandps %ymm7, %ymm4, %ymm8 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm8, %xmm9 +; GFNIAVX1-NEXT: vpxor %xmm6, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm9[8],xmm6[8],xmm9[9],xmm6[9],xmm9[10],xmm6[10],xmm9[11],xmm6[11],xmm9[12],xmm6[12],xmm9[13],xmm6[13],xmm9[14],xmm6[14],xmm9[15],xmm6[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm4 = xmm10[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm4, %xmm11 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [1065353216,1065353216,1065353216,1065353216] +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vcvttps2dq %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm10 = xmm10[0],zero,xmm10[1],zero,xmm10[2],zero,xmm10[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vcvttps2dq %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpackusdw %xmm11, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm11 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm12 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm13 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] +; GFNIAVX1-NEXT: vpmullw %xmm10, %xmm13, %xmm10 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm13 = xmm9[0],zero,zero,zero,xmm9[1],zero,zero,zero,xmm9[2],zero,zero,zero,xmm9[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vcvttps2dq %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm9 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero,xmm9[4],zero,xmm9[5],zero,xmm9[6],zero,xmm9[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm9 = xmm9[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vcvttps2dq %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpackusdw %xmm9, %xmm13, %xmm9 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] +; GFNIAVX1-NEXT: vpmullw %xmm9, %xmm11, %xmm9 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpackuswb %xmm10, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm8[8],xmm6[8],xmm8[9],xmm6[9],xmm8[10],xmm6[10],xmm8[11],xmm6[11],xmm8[12],xmm6[12],xmm8[13],xmm6[13],xmm8[14],xmm6[14],xmm8[15],xmm6[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm11 = xmm10[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vcvttps2dq %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm10 = xmm10[0],zero,xmm10[1],zero,xmm10[2],zero,xmm10[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vcvttps2dq %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpackusdw %xmm11, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm10, %xmm11, %xmm10 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm11 = xmm8[0],zero,zero,zero,xmm8[1],zero,zero,zero,xmm8[2],zero,zero,zero,xmm8[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vcvttps2dq %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm8 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero,xmm8[4],zero,xmm8[5],zero,xmm8[6],zero,xmm8[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm8 = xmm8[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vcvttps2dq %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpackusdw %xmm8, %xmm11, %xmm8 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm0, %xmm8, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm10, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm9, %ymm0, %ymm0 +; GFNIAVX1-NEXT: vandps %ymm7, %ymm5, %ymm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm5[8],xmm6[8],xmm5[9],xmm6[9],xmm5[10],xmm6[10],xmm5[11],xmm6[11],xmm5[12],xmm6[12],xmm5[13],xmm6[13],xmm5[14],xmm6[14],xmm5[15],xmm6[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm8 = xmm7[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vcvttps2dq %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm7 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vcvttps2dq %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpackusdw %xmm8, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm8 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm3, %xmm9 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm9[8],xmm8[8],xmm9[9],xmm8[9],xmm9[10],xmm8[10],xmm9[11],xmm8[11],xmm9[12],xmm8[12],xmm9[13],xmm8[13],xmm9[14],xmm8[14],xmm9[15],xmm8[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm10, %xmm7 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm10 = xmm5[0],zero,zero,zero,xmm5[1],zero,zero,zero,xmm5[2],zero,zero,zero,xmm5[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vcvttps2dq %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm5 = xmm5[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vcvttps2dq %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpackusdw %xmm5, %xmm10, %xmm5 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm9[0],xmm8[0],xmm9[1],xmm8[1],xmm9[2],xmm8[2],xmm9[3],xmm8[3],xmm9[4],xmm8[4],xmm9[5],xmm8[5],xmm9[6],xmm8[6],xmm9[7],xmm8[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm8, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpackuswb %xmm7, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm2[8],xmm6[8],xmm2[9],xmm6[9],xmm2[10],xmm6[10],xmm2[11],xmm6[11],xmm2[12],xmm6[12],xmm2[13],xmm6[13],xmm2[14],xmm6[14],xmm2[15],xmm6[15] +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm7 = xmm6[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vcvttps2dq %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpmovzxwd {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; GFNIAVX1-NEXT: vpslld $23, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vcvttps2dq %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpackusdw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] +; GFNIAVX1-NEXT: vpmullw %xmm6, %xmm7, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpmovzxbd {{.*#+}} xmm7 = xmm2[0],zero,zero,zero,xmm2[1],zero,zero,zero,xmm2[2],zero,zero,zero,xmm2[3],zero,zero,zero +; GFNIAVX1-NEXT: vpslld $23, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vcvttps2dq %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; GFNIAVX1-NEXT: vpunpckhwd {{.*#+}} xmm2 = xmm2[4,4,5,5,6,6,7,7] +; GFNIAVX1-NEXT: vpslld $23, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpaddd %xmm4, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vcvttps2dq %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackusdw %xmm2, %xmm7, %xmm2 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNIAVX1-NEXT: vpmullw %xmm2, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm5, %ymm1, %ymm1 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: var_fshl_v64i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm7 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; GFNIAVX2-NEXT: vpxor %xmm6, %xmm6, %xmm6 +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm8 = ymm6[4],ymm7[4],ymm6[5],ymm7[5],ymm6[6],ymm7[6],ymm6[7],ymm7[7],ymm6[12],ymm7[12],ymm6[13],ymm7[13],ymm6[14],ymm7[14],ymm6[15],ymm7[15] +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm9 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX2-NEXT: vpand %ymm4, %ymm9, %ymm4 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm4[8],ymm6[8],ymm4[9],ymm6[9],ymm4[10],ymm6[10],ymm4[11],ymm6[11],ymm4[12],ymm6[12],ymm4[13],ymm6[13],ymm4[14],ymm6[14],ymm4[15],ymm6[15],ymm4[24],ymm6[24],ymm4[25],ymm6[25],ymm4[26],ymm6[26],ymm4[27],ymm6[27],ymm4[28],ymm6[28],ymm4[29],ymm6[29],ymm4[30],ymm6[30],ymm4[31],ymm6[31] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm11 = ymm10[4],ymm6[4],ymm10[5],ymm6[5],ymm10[6],ymm6[6],ymm10[7],ymm6[7],ymm10[12],ymm6[12],ymm10[13],ymm6[13],ymm10[14],ymm6[14],ymm10[15],ymm6[15] +; GFNIAVX2-NEXT: vpsllvd %ymm11, %ymm8, %ymm8 +; GFNIAVX2-NEXT: vpsrld $16, %ymm8, %ymm8 +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm7 = ymm6[0],ymm7[0],ymm6[1],ymm7[1],ymm6[2],ymm7[2],ymm6[3],ymm7[3],ymm6[8],ymm7[8],ymm6[9],ymm7[9],ymm6[10],ymm7[10],ymm6[11],ymm7[11] +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm10 = ymm10[0],ymm6[0],ymm10[1],ymm6[1],ymm10[2],ymm6[2],ymm10[3],ymm6[3],ymm10[8],ymm6[8],ymm10[9],ymm6[9],ymm10[10],ymm6[10],ymm10[11],ymm6[11] +; GFNIAVX2-NEXT: vpsllvd %ymm10, %ymm7, %ymm7 +; GFNIAVX2-NEXT: vpsrld $16, %ymm7, %ymm7 +; GFNIAVX2-NEXT: vpackusdw %ymm8, %ymm7, %ymm7 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm7, %ymm7 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm2 = ymm6[4],ymm0[4],ymm6[5],ymm0[5],ymm6[6],ymm0[6],ymm6[7],ymm0[7],ymm6[12],ymm0[12],ymm6[13],ymm0[13],ymm6[14],ymm0[14],ymm6[15],ymm0[15] +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm4[0],ymm6[0],ymm4[1],ymm6[1],ymm4[2],ymm6[2],ymm4[3],ymm6[3],ymm4[4],ymm6[4],ymm4[5],ymm6[5],ymm4[6],ymm6[6],ymm4[7],ymm6[7],ymm4[16],ymm6[16],ymm4[17],ymm6[17],ymm4[18],ymm6[18],ymm4[19],ymm6[19],ymm4[20],ymm6[20],ymm4[21],ymm6[21],ymm4[22],ymm6[22],ymm4[23],ymm6[23] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm8 = ymm4[4],ymm6[4],ymm4[5],ymm6[5],ymm4[6],ymm6[6],ymm4[7],ymm6[7],ymm4[12],ymm6[12],ymm4[13],ymm6[13],ymm4[14],ymm6[14],ymm4[15],ymm6[15] +; GFNIAVX2-NEXT: vpsllvd %ymm8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrld $16, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm0 = ymm6[0],ymm0[0],ymm6[1],ymm0[1],ymm6[2],ymm0[2],ymm6[3],ymm0[3],ymm6[8],ymm0[8],ymm6[9],ymm0[9],ymm6[10],ymm0[10],ymm6[11],ymm0[11] +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm4 = ymm4[0],ymm6[0],ymm4[1],ymm6[1],ymm4[2],ymm6[2],ymm4[3],ymm6[3],ymm4[8],ymm6[8],ymm4[9],ymm6[9],ymm4[10],ymm6[10],ymm4[11],ymm6[11] +; GFNIAVX2-NEXT: vpsllvd %ymm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrld $16, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackusdw %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm7, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm1[8],ymm3[9],ymm1[9],ymm3[10],ymm1[10],ymm3[11],ymm1[11],ymm3[12],ymm1[12],ymm3[13],ymm1[13],ymm3[14],ymm1[14],ymm3[15],ymm1[15],ymm3[24],ymm1[24],ymm3[25],ymm1[25],ymm3[26],ymm1[26],ymm3[27],ymm1[27],ymm3[28],ymm1[28],ymm3[29],ymm1[29],ymm3[30],ymm1[30],ymm3[31],ymm1[31] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm4 = ymm6[4],ymm2[4],ymm6[5],ymm2[5],ymm6[6],ymm2[6],ymm6[7],ymm2[7],ymm6[12],ymm2[12],ymm6[13],ymm2[13],ymm6[14],ymm2[14],ymm6[15],ymm2[15] +; GFNIAVX2-NEXT: vpand %ymm5, %ymm9, %ymm5 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm7 = ymm5[8],ymm6[8],ymm5[9],ymm6[9],ymm5[10],ymm6[10],ymm5[11],ymm6[11],ymm5[12],ymm6[12],ymm5[13],ymm6[13],ymm5[14],ymm6[14],ymm5[15],ymm6[15],ymm5[24],ymm6[24],ymm5[25],ymm6[25],ymm5[26],ymm6[26],ymm5[27],ymm6[27],ymm5[28],ymm6[28],ymm5[29],ymm6[29],ymm5[30],ymm6[30],ymm5[31],ymm6[31] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm8 = ymm7[4],ymm6[4],ymm7[5],ymm6[5],ymm7[6],ymm6[6],ymm7[7],ymm6[7],ymm7[12],ymm6[12],ymm7[13],ymm6[13],ymm7[14],ymm6[14],ymm7[15],ymm6[15] +; GFNIAVX2-NEXT: vpsllvd %ymm8, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpsrld $16, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm2 = ymm6[0],ymm2[0],ymm6[1],ymm2[1],ymm6[2],ymm2[2],ymm6[3],ymm2[3],ymm6[8],ymm2[8],ymm6[9],ymm2[9],ymm6[10],ymm2[10],ymm6[11],ymm2[11] +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm7 = ymm7[0],ymm6[0],ymm7[1],ymm6[1],ymm7[2],ymm6[2],ymm7[3],ymm6[3],ymm7[8],ymm6[8],ymm7[9],ymm6[9],ymm7[10],ymm6[10],ymm7[11],ymm6[11] +; GFNIAVX2-NEXT: vpsllvd %ymm7, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrld $16, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpackusdw %ymm4, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm3[0],ymm1[0],ymm3[1],ymm1[1],ymm3[2],ymm1[2],ymm3[3],ymm1[3],ymm3[4],ymm1[4],ymm3[5],ymm1[5],ymm3[6],ymm1[6],ymm3[7],ymm1[7],ymm3[16],ymm1[16],ymm3[17],ymm1[17],ymm3[18],ymm1[18],ymm3[19],ymm1[19],ymm3[20],ymm1[20],ymm3[21],ymm1[21],ymm3[22],ymm1[22],ymm3[23],ymm1[23] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm3 = ymm6[4],ymm1[4],ymm6[5],ymm1[5],ymm6[6],ymm1[6],ymm6[7],ymm1[7],ymm6[12],ymm1[12],ymm6[13],ymm1[13],ymm6[14],ymm1[14],ymm6[15],ymm1[15] +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm5[0],ymm6[0],ymm5[1],ymm6[1],ymm5[2],ymm6[2],ymm5[3],ymm6[3],ymm5[4],ymm6[4],ymm5[5],ymm6[5],ymm5[6],ymm6[6],ymm5[7],ymm6[7],ymm5[16],ymm6[16],ymm5[17],ymm6[17],ymm5[18],ymm6[18],ymm5[19],ymm6[19],ymm5[20],ymm6[20],ymm5[21],ymm6[21],ymm5[22],ymm6[22],ymm5[23],ymm6[23] +; GFNIAVX2-NEXT: vpunpckhwd {{.*#+}} ymm5 = ymm4[4],ymm6[4],ymm4[5],ymm6[5],ymm4[6],ymm6[6],ymm4[7],ymm6[7],ymm4[12],ymm6[12],ymm4[13],ymm6[13],ymm4[14],ymm6[14],ymm4[15],ymm6[15] +; GFNIAVX2-NEXT: vpsllvd %ymm5, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpsrld $16, %ymm3, %ymm3 +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm1 = ymm6[0],ymm1[0],ymm6[1],ymm1[1],ymm6[2],ymm1[2],ymm6[3],ymm1[3],ymm6[8],ymm1[8],ymm6[9],ymm1[9],ymm6[10],ymm1[10],ymm6[11],ymm1[11] +; GFNIAVX2-NEXT: vpunpcklwd {{.*#+}} ymm4 = ymm4[0],ymm6[0],ymm4[1],ymm6[1],ymm4[2],ymm6[2],ymm4[3],ymm6[3],ymm4[8],ymm6[8],ymm4[9],ymm6[9],ymm4[10],ymm6[10],ymm4[11],ymm6[11] +; GFNIAVX2-NEXT: vpsllvd %ymm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrld $16, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpackusdw %ymm3, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: var_fshl_v64i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm4 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm3, %ymm5 +; GFNIAVX512VL-NEXT: vpsrlw $4, %ymm5, %ymm3 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm6 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm3, %ymm7 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} zmm8 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX512VL-NEXT: vpandq %zmm8, %zmm2, %zmm2 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm2, %ymm3 +; GFNIAVX512VL-NEXT: vpxor %ymm3, %ymm8, %ymm9 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm9, %ymm9 +; GFNIAVX512VL-NEXT: vpblendvb %ymm9, %ymm7, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpsrlw $2, %ymm5, %ymm7 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm10 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNIAVX512VL-NEXT: vpand %ymm7, %ymm10, %ymm7 +; GFNIAVX512VL-NEXT: vpaddb %ymm9, %ymm9, %ymm9 +; GFNIAVX512VL-NEXT: vpblendvb %ymm9, %ymm7, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm5, %ymm7 +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm7, %ymm7 +; GFNIAVX512VL-NEXT: vpaddb %ymm9, %ymm9, %ymm9 +; GFNIAVX512VL-NEXT: vpblendvb %ymm9, %ymm7, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $4, %ymm1, %ymm7 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm7, %ymm6 +; GFNIAVX512VL-NEXT: vpxor %ymm2, %ymm8, %ymm7 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm7, %ymm7 +; GFNIAVX512VL-NEXT: vpblendvb %ymm7, %ymm6, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $2, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm10, %ymm6 +; GFNIAVX512VL-NEXT: vpaddb %ymm7, %ymm7, %ymm7 +; GFNIAVX512VL-NEXT: vpblendvb %ymm7, %ymm6, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm6, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm7, %ymm7, %ymm6 +; GFNIAVX512VL-NEXT: vpblendvb %ymm6, %ymm4, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm5, %zmm1, %zmm1 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $4, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm6 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $2, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm7 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNIAVX512VL-NEXT: vpand %ymm7, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm4, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm5, %ymm4, %ymm3 +; GFNIAVX512VL-NEXT: vpsllw $4, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsllw $2, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpand %ymm7, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm2, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpaddb %ymm0, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm2, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: vporq %zmm1, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: var_fshl_v64i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] +; GFNIAVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm2, %zmm2 +; GFNIAVX512BW-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm5 = zmm2[8],zmm4[8],zmm2[9],zmm4[9],zmm2[10],zmm4[10],zmm2[11],zmm4[11],zmm2[12],zmm4[12],zmm2[13],zmm4[13],zmm2[14],zmm4[14],zmm2[15],zmm4[15],zmm2[24],zmm4[24],zmm2[25],zmm4[25],zmm2[26],zmm4[26],zmm2[27],zmm4[27],zmm2[28],zmm4[28],zmm2[29],zmm4[29],zmm2[30],zmm4[30],zmm2[31],zmm4[31],zmm2[40],zmm4[40],zmm2[41],zmm4[41],zmm2[42],zmm4[42],zmm2[43],zmm4[43],zmm2[44],zmm4[44],zmm2[45],zmm4[45],zmm2[46],zmm4[46],zmm2[47],zmm4[47],zmm2[56],zmm4[56],zmm2[57],zmm4[57],zmm2[58],zmm4[58],zmm2[59],zmm4[59],zmm2[60],zmm4[60],zmm2[61],zmm4[61],zmm2[62],zmm4[62],zmm2[63],zmm4[63] +; GFNIAVX512BW-NEXT: vpsllvw %zmm5, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm2[0],zmm4[0],zmm2[1],zmm4[1],zmm2[2],zmm4[2],zmm2[3],zmm4[3],zmm2[4],zmm4[4],zmm2[5],zmm4[5],zmm2[6],zmm4[6],zmm2[7],zmm4[7],zmm2[16],zmm4[16],zmm2[17],zmm4[17],zmm2[18],zmm4[18],zmm2[19],zmm4[19],zmm2[20],zmm4[20],zmm2[21],zmm4[21],zmm2[22],zmm4[22],zmm2[23],zmm4[23],zmm2[32],zmm4[32],zmm2[33],zmm4[33],zmm2[34],zmm4[34],zmm2[35],zmm4[35],zmm2[36],zmm4[36],zmm2[37],zmm4[37],zmm2[38],zmm4[38],zmm2[39],zmm4[39],zmm2[48],zmm4[48],zmm2[49],zmm4[49],zmm2[50],zmm4[50],zmm2[51],zmm4[51],zmm2[52],zmm4[52],zmm2[53],zmm4[53],zmm2[54],zmm4[54],zmm2[55],zmm4[55] +; GFNIAVX512BW-NEXT: vpsllvw %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpackuswb %zmm3, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: retq + %res = call <64 x i8> @llvm.fshl.v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) + ret <64 x i8> %res +} + +define <64 x i8> @var_fshr_v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) nounwind { +; GFNISSE-LABEL: var_fshr_v64i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm7, %xmm10 +; GFNISSE-NEXT: movdqa %xmm6, %xmm7 +; GFNISSE-NEXT: movdqa %xmm5, %xmm6 +; GFNISSE-NEXT: movdqa %xmm4, %xmm5 +; GFNISSE-NEXT: movdqa %xmm3, %xmm4 +; GFNISSE-NEXT: movdqa %xmm2, %xmm3 +; GFNISSE-NEXT: movdqa %xmm1, %xmm2 +; GFNISSE-NEXT: movdqa %xmm0, %xmm1 +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm9 +; GFNISSE-NEXT: movdqa %xmm5, %xmm12 +; GFNISSE-NEXT: psrlw $4, %xmm12 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm12 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm11 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm11, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm12, %xmm5 +; GFNISSE-NEXT: movdqa %xmm5, %xmm13 +; GFNISSE-NEXT: psrlw $2, %xmm13 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm13 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm13, %xmm5 +; GFNISSE-NEXT: movdqa %xmm5, %xmm14 +; GFNISSE-NEXT: psrlw $1, %xmm14 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm14 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm14, %xmm5 +; GFNISSE-NEXT: paddb %xmm1, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm15 +; GFNISSE-NEXT: psllw $4, %xmm15 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm15 +; GFNISSE-NEXT: movdqa %xmm11, %xmm12 +; GFNISSE-NEXT: pandn %xmm11, %xmm9 +; GFNISSE-NEXT: psllw $5, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm15, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm8 +; GFNISSE-NEXT: psllw $2, %xmm8 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm1 +; GFNISSE-NEXT: movdqa %xmm1, %xmm8 +; GFNISSE-NEXT: paddb %xmm1, %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm1 +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm9 +; GFNISSE-NEXT: movdqa %xmm6, %xmm8 +; GFNISSE-NEXT: psrlw $4, %xmm8 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm11 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNISSE-NEXT: pand %xmm11, %xmm8 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm12, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm6 +; GFNISSE-NEXT: movdqa %xmm6, %xmm8 +; GFNISSE-NEXT: psrlw $2, %xmm8 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm13 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNISSE-NEXT: pand %xmm13, %xmm8 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm6 +; GFNISSE-NEXT: movdqa %xmm6, %xmm8 +; GFNISSE-NEXT: psrlw $1, %xmm8 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm14 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNISSE-NEXT: pand %xmm14, %xmm8 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm6 +; GFNISSE-NEXT: paddb %xmm2, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm8 +; GFNISSE-NEXT: psllw $4, %xmm8 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm15 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNISSE-NEXT: pand %xmm15, %xmm8 +; GFNISSE-NEXT: pandn %xmm12, %xmm9 +; GFNISSE-NEXT: psllw $5, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm8 +; GFNISSE-NEXT: psllw $2, %xmm8 +; GFNISSE-NEXT: movdqa {{.*#+}} xmm0 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNISSE-NEXT: pand %xmm0, %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm2 +; GFNISSE-NEXT: movdqa %xmm2, %xmm8 +; GFNISSE-NEXT: paddb %xmm2, %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm2 +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm9 +; GFNISSE-NEXT: movdqa %xmm7, %xmm8 +; GFNISSE-NEXT: psrlw $4, %xmm8 +; GFNISSE-NEXT: pand %xmm11, %xmm8 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm12, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm7 +; GFNISSE-NEXT: movdqa %xmm7, %xmm8 +; GFNISSE-NEXT: psrlw $2, %xmm8 +; GFNISSE-NEXT: pand %xmm13, %xmm8 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm7 +; GFNISSE-NEXT: movdqa %xmm7, %xmm8 +; GFNISSE-NEXT: psrlw $1, %xmm8 +; GFNISSE-NEXT: pand %xmm14, %xmm8 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm7 +; GFNISSE-NEXT: paddb %xmm3, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm8 +; GFNISSE-NEXT: psllw $4, %xmm8 +; GFNISSE-NEXT: pand %xmm15, %xmm8 +; GFNISSE-NEXT: pandn %xmm12, %xmm9 +; GFNISSE-NEXT: psllw $5, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm8 +; GFNISSE-NEXT: psllw $2, %xmm8 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm3 +; GFNISSE-NEXT: movdqa %xmm3, %xmm8 +; GFNISSE-NEXT: paddb %xmm3, %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm3 +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm9 +; GFNISSE-NEXT: movdqa %xmm10, %xmm8 +; GFNISSE-NEXT: psrlw $4, %xmm8 +; GFNISSE-NEXT: pand %xmm11, %xmm8 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm12, %xmm0 +; GFNISSE-NEXT: psllw $5, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm10 +; GFNISSE-NEXT: movdqa %xmm10, %xmm8 +; GFNISSE-NEXT: psrlw $2, %xmm8 +; GFNISSE-NEXT: pand %xmm13, %xmm8 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm10 +; GFNISSE-NEXT: movdqa %xmm10, %xmm8 +; GFNISSE-NEXT: psrlw $1, %xmm8 +; GFNISSE-NEXT: pand %xmm14, %xmm8 +; GFNISSE-NEXT: paddb %xmm0, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm10 +; GFNISSE-NEXT: paddb %xmm4, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm8 +; GFNISSE-NEXT: psllw $4, %xmm8 +; GFNISSE-NEXT: pand %xmm15, %xmm8 +; GFNISSE-NEXT: pandn %xmm12, %xmm9 +; GFNISSE-NEXT: psllw $5, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm8 +; GFNISSE-NEXT: psllw $2, %xmm8 +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm4 +; GFNISSE-NEXT: movdqa %xmm4, %xmm8 +; GFNISSE-NEXT: paddb %xmm4, %xmm8 +; GFNISSE-NEXT: paddb %xmm9, %xmm9 +; GFNISSE-NEXT: movdqa %xmm9, %xmm0 +; GFNISSE-NEXT: pblendvb %xmm0, %xmm8, %xmm4 +; GFNISSE-NEXT: por %xmm5, %xmm1 +; GFNISSE-NEXT: por %xmm6, %xmm2 +; GFNISSE-NEXT: por %xmm7, %xmm3 +; GFNISSE-NEXT: por %xmm10, %xmm4 +; GFNISSE-NEXT: movdqa %xmm1, %xmm0 +; GFNISSE-NEXT: movdqa %xmm2, %xmm1 +; GFNISSE-NEXT: movdqa %xmm3, %xmm2 +; GFNISSE-NEXT: movdqa %xmm4, %xmm3 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: var_fshr_v64i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm8 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm8, %xmm6 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm7 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNIAVX1-NEXT: vpand %xmm7, %xmm6, %xmm9 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} ymm6 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX1-NEXT: vandps %ymm6, %ymm4, %ymm11 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm11, %xmm10 +; GFNIAVX1-NEXT: vpsllw $5, %xmm10, %xmm12 +; GFNIAVX1-NEXT: vpblendvb %xmm12, %xmm9, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm8, %xmm9 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNIAVX1-NEXT: vpand %xmm4, %xmm9, %xmm9 +; GFNIAVX1-NEXT: vpaddb %xmm12, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpblendvb %xmm12, %xmm9, %xmm8, %xmm9 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm9, %xmm13 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm8 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNIAVX1-NEXT: vpand %xmm8, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm12, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpblendvb %xmm12, %xmm13, %xmm9, %xmm12 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm9 +; GFNIAVX1-NEXT: vpaddb %xmm9, %xmm9, %xmm13 +; GFNIAVX1-NEXT: vpsllw $4, %xmm13, %xmm14 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm9 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNIAVX1-NEXT: vpand %xmm9, %xmm14, %xmm14 +; GFNIAVX1-NEXT: vpxor %xmm6, %xmm10, %xmm10 +; GFNIAVX1-NEXT: vpsllw $5, %xmm10, %xmm15 +; GFNIAVX1-NEXT: vpblendvb %xmm15, %xmm14, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpsllw $2, %xmm13, %xmm14 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm10 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNIAVX1-NEXT: vpand %xmm10, %xmm14, %xmm14 +; GFNIAVX1-NEXT: vpaddb %xmm15, %xmm15, %xmm15 +; GFNIAVX1-NEXT: vpblendvb %xmm15, %xmm14, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm13, %xmm13, %xmm14 +; GFNIAVX1-NEXT: vpaddb %xmm15, %xmm15, %xmm15 +; GFNIAVX1-NEXT: vpblendvb %xmm15, %xmm14, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpor %xmm12, %xmm13, %xmm12 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm2, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm7, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpsllw $5, %xmm11, %xmm14 +; GFNIAVX1-NEXT: vpblendvb %xmm14, %xmm13, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm2, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm14, %xmm14, %xmm14 +; GFNIAVX1-NEXT: vpblendvb %xmm14, %xmm13, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm2, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm8, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm14, %xmm14, %xmm14 +; GFNIAVX1-NEXT: vpblendvb %xmm14, %xmm13, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpaddb %xmm0, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsllw $4, %xmm0, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm9, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpxor %xmm6, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpsllw $5, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpblendvb %xmm11, %xmm13, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsllw $2, %xmm0, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm10, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm11, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpblendvb %xmm11, %xmm13, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpaddb %xmm0, %xmm0, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm11, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpblendvb %xmm11, %xmm13, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpor %xmm2, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm12, %ymm0, %ymm0 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm3, %xmm11 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm11, %xmm2 +; GFNIAVX1-NEXT: vpand %xmm7, %xmm2, %xmm12 +; GFNIAVX1-NEXT: vandps %ymm6, %ymm5, %ymm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm5 +; GFNIAVX1-NEXT: vpsllw $5, %xmm5, %xmm13 +; GFNIAVX1-NEXT: vpblendvb %xmm13, %xmm12, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm11, %xmm12 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpaddb %xmm13, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpblendvb %xmm13, %xmm12, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm11, %xmm12 +; GFNIAVX1-NEXT: vpand %xmm8, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpaddb %xmm13, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpblendvb %xmm13, %xmm12, %xmm11, %xmm11 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm12 +; GFNIAVX1-NEXT: vpaddb %xmm12, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpsllw $4, %xmm12, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm9, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpxor %xmm6, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpsllw $5, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm13, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpsllw $2, %xmm12, %xmm13 +; GFNIAVX1-NEXT: vpand %xmm10, %xmm13, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm5, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm13, %xmm12, %xmm12 +; GFNIAVX1-NEXT: vpaddb %xmm12, %xmm12, %xmm13 +; GFNIAVX1-NEXT: vpaddb %xmm5, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpblendvb %xmm5, %xmm13, %xmm12, %xmm5 +; GFNIAVX1-NEXT: vpor %xmm5, %xmm11, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $4, %xmm3, %xmm11 +; GFNIAVX1-NEXT: vpand %xmm7, %xmm11, %xmm7 +; GFNIAVX1-NEXT: vpsllw $5, %xmm2, %xmm11 +; GFNIAVX1-NEXT: vpblendvb %xmm11, %xmm7, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpsrlw $2, %xmm3, %xmm7 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm7, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm11, %xmm11, %xmm7 +; GFNIAVX1-NEXT: vpblendvb %xmm7, %xmm4, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpsrlw $1, %xmm3, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm8, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm7, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpblendvb %xmm7, %xmm4, %xmm3, %xmm3 +; GFNIAVX1-NEXT: vpaddb %xmm1, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsllw $4, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm9, %xmm4 +; GFNIAVX1-NEXT: vpxor %xmm6, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsllw $5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsllw $2, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpand %xmm4, %xmm10, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm2, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpaddb %xmm1, %xmm1, %xmm4 +; GFNIAVX1-NEXT: vpaddb %xmm2, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpblendvb %xmm2, %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpor %xmm3, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm5, %ymm1, %ymm1 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: var_fshr_v64i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpsrlw $4, %ymm2, %ymm6 +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm7 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNIAVX2-NEXT: vpand %ymm7, %ymm6, %ymm8 +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm6 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX2-NEXT: vpand %ymm6, %ymm4, %ymm9 +; GFNIAVX2-NEXT: vpsllw $5, %ymm9, %ymm9 +; GFNIAVX2-NEXT: vpblendvb %ymm9, %ymm8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $2, %ymm2, %ymm8 +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm10 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNIAVX2-NEXT: vpand %ymm10, %ymm8, %ymm8 +; GFNIAVX2-NEXT: vpaddb %ymm9, %ymm9, %ymm9 +; GFNIAVX2-NEXT: vpblendvb %ymm9, %ymm8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $1, %ymm2, %ymm8 +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm11 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNIAVX2-NEXT: vpand %ymm11, %ymm8, %ymm8 +; GFNIAVX2-NEXT: vpaddb %ymm9, %ymm9, %ymm9 +; GFNIAVX2-NEXT: vpblendvb %ymm9, %ymm8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpaddb %ymm0, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsllw $4, %ymm0, %ymm8 +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm9 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNIAVX2-NEXT: vpand %ymm9, %ymm8, %ymm8 +; GFNIAVX2-NEXT: vpandn %ymm6, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpsllw $5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsllw $2, %ymm0, %ymm8 +; GFNIAVX2-NEXT: vpbroadcastb {{.*#+}} ymm12 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNIAVX2-NEXT: vpand %ymm12, %ymm8, %ymm8 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpaddb %ymm0, %ymm0, %ymm8 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpor %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $4, %ymm3, %ymm2 +; GFNIAVX2-NEXT: vpand %ymm7, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpand %ymm6, %ymm5, %ymm4 +; GFNIAVX2-NEXT: vpsllw $5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm2, %ymm3, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $2, %ymm2, %ymm3 +; GFNIAVX2-NEXT: vpand %ymm3, %ymm10, %ymm3 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm3, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $1, %ymm2, %ymm3 +; GFNIAVX2-NEXT: vpand %ymm3, %ymm11, %ymm3 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm3, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpaddb %ymm1, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsllw $4, %ymm1, %ymm3 +; GFNIAVX2-NEXT: vpand %ymm3, %ymm9, %ymm3 +; GFNIAVX2-NEXT: vpandn %ymm6, %ymm5, %ymm4 +; GFNIAVX2-NEXT: vpsllw $5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm3, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsllw $2, %ymm1, %ymm3 +; GFNIAVX2-NEXT: vpand %ymm3, %ymm12, %ymm3 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm3, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpaddb %ymm1, %ymm1, %ymm3 +; GFNIAVX2-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpblendvb %ymm4, %ymm3, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpor %ymm2, %ymm1, %ymm1 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: var_fshr_v64i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $4, %ymm4, %ymm3 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm5 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm3, %ymm6 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} zmm7 = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7] +; GFNIAVX512VL-NEXT: vpandq %zmm7, %zmm2, %zmm2 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm2, %ymm3 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm3, %ymm8 +; GFNIAVX512VL-NEXT: vpblendvb %ymm8, %ymm6, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $2, %ymm4, %ymm6 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm9 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm9, %ymm6 +; GFNIAVX512VL-NEXT: vpaddb %ymm8, %ymm8, %ymm8 +; GFNIAVX512VL-NEXT: vpblendvb %ymm8, %ymm6, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm4, %ymm6 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm10 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm10, %ymm6 +; GFNIAVX512VL-NEXT: vpaddb %ymm8, %ymm8, %ymm8 +; GFNIAVX512VL-NEXT: vpblendvb %ymm8, %ymm6, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $4, %ymm1, %ymm6 +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm6, %ymm5 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm2, %ymm6 +; GFNIAVX512VL-NEXT: vpblendvb %ymm6, %ymm5, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $2, %ymm1, %ymm5 +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm9, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm6, %ymm6, %ymm6 +; GFNIAVX512VL-NEXT: vpblendvb %ymm6, %ymm5, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vpsrlw $1, %ymm1, %ymm5 +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm10, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm6, %ymm6, %ymm6 +; GFNIAVX512VL-NEXT: vpblendvb %ymm6, %ymm5, %ymm1, %ymm1 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm1 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm4, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $4, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm6 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpxor %ymm7, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsllw $2, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm8 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] +; GFNIAVX512VL-NEXT: vpand %ymm5, %ymm8, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm4, %ymm4, %ymm5 +; GFNIAVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpblendvb %ymm3, %ymm5, %ymm4, %ymm3 +; GFNIAVX512VL-NEXT: vpaddb %ymm0, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsllw $4, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpxor %ymm7, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsllw $5, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsllw $2, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm8, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm2, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpaddb %ymm0, %ymm0, %ymm4 +; GFNIAVX512VL-NEXT: vpaddb %ymm2, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpblendvb %ymm2, %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: vporq %zmm1, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: var_fshr_v64i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] +; GFNIAVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm2, %zmm2 +; GFNIAVX512BW-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm5 = zmm2[8],zmm4[8],zmm2[9],zmm4[9],zmm2[10],zmm4[10],zmm2[11],zmm4[11],zmm2[12],zmm4[12],zmm2[13],zmm4[13],zmm2[14],zmm4[14],zmm2[15],zmm4[15],zmm2[24],zmm4[24],zmm2[25],zmm4[25],zmm2[26],zmm4[26],zmm2[27],zmm4[27],zmm2[28],zmm4[28],zmm2[29],zmm4[29],zmm2[30],zmm4[30],zmm2[31],zmm4[31],zmm2[40],zmm4[40],zmm2[41],zmm4[41],zmm2[42],zmm4[42],zmm2[43],zmm4[43],zmm2[44],zmm4[44],zmm2[45],zmm4[45],zmm2[46],zmm4[46],zmm2[47],zmm4[47],zmm2[56],zmm4[56],zmm2[57],zmm4[57],zmm2[58],zmm4[58],zmm2[59],zmm4[59],zmm2[60],zmm4[60],zmm2[61],zmm4[61],zmm2[62],zmm4[62],zmm2[63],zmm4[63] +; GFNIAVX512BW-NEXT: vpsrlvw %zmm5, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpbroadcastw {{.*#+}} zmm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX512BW-NEXT: vpandq %zmm5, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm2[0],zmm4[0],zmm2[1],zmm4[1],zmm2[2],zmm4[2],zmm2[3],zmm4[3],zmm2[4],zmm4[4],zmm2[5],zmm4[5],zmm2[6],zmm4[6],zmm2[7],zmm4[7],zmm2[16],zmm4[16],zmm2[17],zmm4[17],zmm2[18],zmm4[18],zmm2[19],zmm4[19],zmm2[20],zmm4[20],zmm2[21],zmm4[21],zmm2[22],zmm4[22],zmm2[23],zmm4[23],zmm2[32],zmm4[32],zmm2[33],zmm4[33],zmm2[34],zmm4[34],zmm2[35],zmm4[35],zmm2[36],zmm4[36],zmm2[37],zmm4[37],zmm2[38],zmm4[38],zmm2[39],zmm4[39],zmm2[48],zmm4[48],zmm2[49],zmm4[49],zmm2[50],zmm4[50],zmm2[51],zmm4[51],zmm2[52],zmm4[52],zmm2[53],zmm4[53],zmm2[54],zmm4[54],zmm2[55],zmm4[55] +; GFNIAVX512BW-NEXT: vpsrlvw %zmm1, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpandq %zmm5, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpackuswb %zmm3, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: retq + %res = call <64 x i8> @llvm.fshr.v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) + ret <64 x i8> %res +} + +define <64 x i8> @splatvar_fshl_v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) nounwind { +; GFNISSE-LABEL: splatvar_fshl_v64i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm8 +; GFNISSE-NEXT: movdqa %xmm4, %xmm9 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm0[8],xmm9[9],xmm0[9],xmm9[10],xmm0[10],xmm9[11],xmm0[11],xmm9[12],xmm0[12],xmm9[13],xmm0[13],xmm9[14],xmm0[14],xmm9[15],xmm0[15] +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm8 +; GFNISSE-NEXT: psllw %xmm8, %xmm9 +; GFNISSE-NEXT: psrlw $8, %xmm9 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; GFNISSE-NEXT: psllw %xmm8, %xmm4 +; GFNISSE-NEXT: psrlw $8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm9, %xmm4 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: psllw %xmm8, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm1[0],xmm5[1],xmm1[1],xmm5[2],xmm1[2],xmm5[3],xmm1[3],xmm5[4],xmm1[4],xmm5[5],xmm1[5],xmm5[6],xmm1[6],xmm5[7],xmm1[7] +; GFNISSE-NEXT: psllw %xmm8, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: packuswb %xmm0, %xmm5 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15] +; GFNISSE-NEXT: psllw %xmm8, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm2[0],xmm6[1],xmm2[1],xmm6[2],xmm2[2],xmm6[3],xmm2[3],xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; GFNISSE-NEXT: psllw %xmm8, %xmm6 +; GFNISSE-NEXT: psrlw $8, %xmm6 +; GFNISSE-NEXT: packuswb %xmm0, %xmm6 +; GFNISSE-NEXT: movdqa %xmm7, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15] +; GFNISSE-NEXT: psllw %xmm8, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm3[0],xmm7[1],xmm3[1],xmm7[2],xmm3[2],xmm7[3],xmm3[3],xmm7[4],xmm3[4],xmm7[5],xmm3[5],xmm7[6],xmm3[6],xmm7[7],xmm3[7] +; GFNISSE-NEXT: psllw %xmm8, %xmm7 +; GFNISSE-NEXT: psrlw $8, %xmm7 +; GFNISSE-NEXT: packuswb %xmm0, %xmm7 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: movdqa %xmm5, %xmm1 +; GFNISSE-NEXT: movdqa %xmm6, %xmm2 +; GFNISSE-NEXT: movdqa %xmm7, %xmm3 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: splatvar_fshl_v64i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm6 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm6[8],xmm5[8],xmm6[9],xmm5[9],xmm6[10],xmm5[10],xmm6[11],xmm5[11],xmm6[12],xmm5[12],xmm6[13],xmm5[13],xmm6[14],xmm5[14],xmm6[15],xmm5[15] +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm6[0],xmm5[0],xmm6[1],xmm5[1],xmm6[2],xmm5[2],xmm6[3],xmm5[3],xmm6[4],xmm5[4],xmm6[5],xmm5[5],xmm6[6],xmm5[6],xmm6[7],xmm5[7] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpackuswb %xmm7, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm5, %ymm0, %ymm0 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm3, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm2[8],xmm5[9],xmm2[9],xmm5[10],xmm2[10],xmm5[11],xmm2[11],xmm5[12],xmm2[12],xmm5[13],xmm2[13],xmm5[14],xmm2[14],xmm5[15],xmm2[15] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm5[0],xmm2[0],xmm5[1],xmm2[1],xmm5[2],xmm2[2],xmm5[3],xmm2[3],xmm5[4],xmm2[4],xmm5[5],xmm2[5],xmm5[6],xmm2[6],xmm5[7],xmm2[7] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm5, %xmm5 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNIAVX1-NEXT: vpsllw %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpackuswb %xmm5, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: splatvar_fshl_v64i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpsllw %xmm4, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; GFNIAVX2-NEXT: vpsllw %xmm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm5, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm1[8],ymm3[9],ymm1[9],ymm3[10],ymm1[10],ymm3[11],ymm1[11],ymm3[12],ymm1[12],ymm3[13],ymm1[13],ymm3[14],ymm1[14],ymm3[15],ymm1[15],ymm3[24],ymm1[24],ymm3[25],ymm1[25],ymm3[26],ymm1[26],ymm3[27],ymm1[27],ymm3[28],ymm1[28],ymm3[29],ymm1[29],ymm3[30],ymm1[30],ymm3[31],ymm1[31] +; GFNIAVX2-NEXT: vpsllw %xmm4, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm3[0],ymm1[0],ymm3[1],ymm1[1],ymm3[2],ymm1[2],ymm3[3],ymm1[3],ymm3[4],ymm1[4],ymm3[5],ymm1[5],ymm3[6],ymm1[6],ymm3[7],ymm1[7],ymm3[16],ymm1[16],ymm3[17],ymm1[17],ymm3[18],ymm1[18],ymm3[19],ymm1[19],ymm3[20],ymm1[20],ymm3[21],ymm1[21],ymm3[22],ymm1[22],ymm3[23],ymm1[23] +; GFNIAVX2-NEXT: vpsllw %xmm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: splatvar_fshl_v64i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm3 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm4 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm4[8],ymm3[8],ymm4[9],ymm3[9],ymm4[10],ymm3[10],ymm4[11],ymm3[11],ymm4[12],ymm3[12],ymm4[13],ymm3[13],ymm4[14],ymm3[14],ymm4[15],ymm3[15],ymm4[24],ymm3[24],ymm4[25],ymm3[25],ymm4[26],ymm3[26],ymm4[27],ymm3[27],ymm4[28],ymm3[28],ymm4[29],ymm3[29],ymm4[30],ymm3[30],ymm4[31],ymm3[31] +; GFNIAVX512VL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpsllw %xmm2, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[16],ymm3[16],ymm4[17],ymm3[17],ymm4[18],ymm3[18],ymm4[19],ymm3[19],ymm4[20],ymm3[20],ymm4[21],ymm3[21],ymm4[22],ymm3[22],ymm4[23],ymm3[23] +; GFNIAVX512VL-NEXT: vpsllw %xmm2, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpackuswb %ymm5, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpsllw %xmm2, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpsllw %xmm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: splatvar_fshl_v64i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] +; GFNIAVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512BW-NEXT: vpsllw %xmm2, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] +; GFNIAVX512BW-NEXT: vpsllw %xmm2, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpackuswb %zmm3, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: retq + %splat = shufflevector <64 x i8> %amt, <64 x i8> undef, <64 x i32> zeroinitializer + %res = call <64 x i8> @llvm.fshl.v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %splat) + ret <64 x i8> %res +} + +define <64 x i8> @splatvar_fshr_v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) nounwind { +; GFNISSE-LABEL: splatvar_fshr_v64i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm9 +; GFNISSE-NEXT: movdqa %xmm4, %xmm10 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm0[8],xmm10[9],xmm0[9],xmm10[10],xmm0[10],xmm10[11],xmm0[11],xmm10[12],xmm0[12],xmm10[13],xmm0[13],xmm10[14],xmm0[14],xmm10[15],xmm0[15] +; GFNISSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm9 +; GFNISSE-NEXT: psrlw %xmm9, %xmm10 +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm8 = [255,255,255,255,255,255,255,255] +; GFNISSE-NEXT: pand %xmm8, %xmm10 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; GFNISSE-NEXT: psrlw %xmm9, %xmm4 +; GFNISSE-NEXT: pand %xmm8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm10, %xmm4 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: psrlw %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm1[0],xmm5[1],xmm1[1],xmm5[2],xmm1[2],xmm5[3],xmm1[3],xmm5[4],xmm1[4],xmm5[5],xmm1[5],xmm5[6],xmm1[6],xmm5[7],xmm1[7] +; GFNISSE-NEXT: psrlw %xmm9, %xmm5 +; GFNISSE-NEXT: pand %xmm8, %xmm5 +; GFNISSE-NEXT: packuswb %xmm0, %xmm5 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15] +; GFNISSE-NEXT: psrlw %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm2[0],xmm6[1],xmm2[1],xmm6[2],xmm2[2],xmm6[3],xmm2[3],xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; GFNISSE-NEXT: psrlw %xmm9, %xmm6 +; GFNISSE-NEXT: pand %xmm8, %xmm6 +; GFNISSE-NEXT: packuswb %xmm0, %xmm6 +; GFNISSE-NEXT: movdqa %xmm7, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15] +; GFNISSE-NEXT: psrlw %xmm9, %xmm0 +; GFNISSE-NEXT: pand %xmm8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm3[0],xmm7[1],xmm3[1],xmm7[2],xmm3[2],xmm7[3],xmm3[3],xmm7[4],xmm3[4],xmm7[5],xmm3[5],xmm7[6],xmm3[6],xmm7[7],xmm3[7] +; GFNISSE-NEXT: psrlw %xmm9, %xmm7 +; GFNISSE-NEXT: pand %xmm7, %xmm8 +; GFNISSE-NEXT: packuswb %xmm0, %xmm8 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: movdqa %xmm5, %xmm1 +; GFNISSE-NEXT: movdqa %xmm6, %xmm2 +; GFNISSE-NEXT: movdqa %xmm8, %xmm3 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: splatvar_fshr_v64i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm6 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm7 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm7[8],xmm6[8],xmm7[9],xmm6[9],xmm7[10],xmm6[10],xmm7[11],xmm6[11],xmm7[12],xmm6[12],xmm7[13],xmm6[13],xmm7[14],xmm6[14],xmm7[15],xmm6[15] +; GFNIAVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm5, %xmm8 +; GFNIAVX1-NEXT: vbroadcastss {{.*#+}} xmm5 = [255,255,255,255,255,255,255,255] +; GFNIAVX1-NEXT: vpand %xmm5, %xmm8, %xmm8 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm7[0],xmm6[0],xmm7[1],xmm6[1],xmm7[2],xmm6[2],xmm7[3],xmm6[3],xmm7[4],xmm6[4],xmm7[5],xmm6[5],xmm7[6],xmm6[6],xmm7[7],xmm6[7] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpackuswb %xmm8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm7, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm6, %ymm0, %ymm0 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm3, %xmm6 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm6[8],xmm2[8],xmm6[9],xmm2[9],xmm6[10],xmm2[10],xmm6[11],xmm2[11],xmm6[12],xmm2[12],xmm6[13],xmm2[13],xmm6[14],xmm2[14],xmm6[15],xmm2[15] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm7, %xmm7 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm6[0],xmm2[0],xmm6[1],xmm2[1],xmm6[2],xmm2[2],xmm6[3],xmm2[3],xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackuswb %xmm7, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNIAVX1-NEXT: vpsrlw %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpand %xmm5, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: splatvar_fshr_v64i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; GFNIAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm4, %xmm4 +; GFNIAVX2-NEXT: vpsrlw %xmm4, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpbroadcastw {{.*#+}} ymm6 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX2-NEXT: vpand %ymm6, %ymm5, %ymm5 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; GFNIAVX2-NEXT: vpsrlw %xmm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpand %ymm6, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm5, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm1[8],ymm3[9],ymm1[9],ymm3[10],ymm1[10],ymm3[11],ymm1[11],ymm3[12],ymm1[12],ymm3[13],ymm1[13],ymm3[14],ymm1[14],ymm3[15],ymm1[15],ymm3[24],ymm1[24],ymm3[25],ymm1[25],ymm3[26],ymm1[26],ymm3[27],ymm1[27],ymm3[28],ymm1[28],ymm3[29],ymm1[29],ymm3[30],ymm1[30],ymm3[31],ymm1[31] +; GFNIAVX2-NEXT: vpsrlw %xmm4, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpand %ymm6, %ymm2, %ymm2 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm3[0],ymm1[0],ymm3[1],ymm1[1],ymm3[2],ymm1[2],ymm3[3],ymm1[3],ymm3[4],ymm1[4],ymm3[5],ymm1[5],ymm3[6],ymm1[6],ymm3[7],ymm1[7],ymm3[16],ymm1[16],ymm3[17],ymm1[17],ymm3[18],ymm1[18],ymm3[19],ymm1[19],ymm3[20],ymm1[20],ymm3[21],ymm1[21],ymm3[22],ymm1[22],ymm3[23],ymm1[23] +; GFNIAVX2-NEXT: vpsrlw %xmm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpand %ymm6, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: splatvar_fshr_v64i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm3 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm4 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm4[8],ymm3[8],ymm4[9],ymm3[9],ymm4[10],ymm3[10],ymm4[11],ymm3[11],ymm4[12],ymm3[12],ymm4[13],ymm3[13],ymm4[14],ymm3[14],ymm4[15],ymm3[15],ymm4[24],ymm3[24],ymm4[25],ymm3[25],ymm4[26],ymm3[26],ymm4[27],ymm3[27],ymm4[28],ymm3[28],ymm4[29],ymm3[29],ymm4[30],ymm3[30],ymm4[31],ymm3[31] +; GFNIAVX512VL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm6 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm5, %ymm5 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[16],ymm3[16],ymm4[17],ymm3[17],ymm4[18],ymm3[18],ymm4[19],ymm3[19],ymm4[20],ymm3[20],ymm4[21],ymm3[21],ymm4[22],ymm3[22],ymm4[23],ymm3[23] +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpackuswb %ymm5, %ymm3, %ymm3 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpsrlw %xmm2, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpand %ymm6, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: splatvar_fshr_v64i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] +; GFNIAVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 +; GFNIAVX512BW-NEXT: vpsrlw %xmm2, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpbroadcastw {{.*#+}} zmm4 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; GFNIAVX512BW-NEXT: vpandq %zmm4, %zmm3, %zmm3 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] +; GFNIAVX512BW-NEXT: vpsrlw %xmm2, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpandq %zmm4, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpackuswb %zmm3, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: retq + %splat = shufflevector <64 x i8> %amt, <64 x i8> undef, <64 x i32> zeroinitializer + %res = call <64 x i8> @llvm.fshr.v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %splat) + ret <64 x i8> %res +} + +define <64 x i8> @constant_fshl_v64i8(<64 x i8> %a, <64 x i8> %b) nounwind { +; GFNISSE-LABEL: constant_fshl_v64i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm4, %xmm10 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm0[8],xmm10[9],xmm0[9],xmm10[10],xmm0[10],xmm10[11],xmm0[11],xmm10[12],xmm0[12],xmm10[13],xmm0[13],xmm10[14],xmm0[14],xmm10[15],xmm0[15] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm9 = [1,128,64,32,16,8,4,2] +; GFNISSE-NEXT: pmullw %xmm9, %xmm10 +; GFNISSE-NEXT: psrlw $8, %xmm10 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm8 = [1,2,4,8,16,32,64,128] +; GFNISSE-NEXT: pmullw %xmm8, %xmm4 +; GFNISSE-NEXT: psrlw $8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm10, %xmm4 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: pmullw %xmm9, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm1[0],xmm5[1],xmm1[1],xmm5[2],xmm1[2],xmm5[3],xmm1[3],xmm5[4],xmm1[4],xmm5[5],xmm1[5],xmm5[6],xmm1[6],xmm5[7],xmm1[7] +; GFNISSE-NEXT: pmullw %xmm8, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: packuswb %xmm0, %xmm5 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15] +; GFNISSE-NEXT: pmullw %xmm9, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm2[0],xmm6[1],xmm2[1],xmm6[2],xmm2[2],xmm6[3],xmm2[3],xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; GFNISSE-NEXT: pmullw %xmm8, %xmm6 +; GFNISSE-NEXT: psrlw $8, %xmm6 +; GFNISSE-NEXT: packuswb %xmm0, %xmm6 +; GFNISSE-NEXT: movdqa %xmm7, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15] +; GFNISSE-NEXT: pmullw %xmm9, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm3[0],xmm7[1],xmm3[1],xmm7[2],xmm3[2],xmm7[3],xmm3[3],xmm7[4],xmm3[4],xmm7[5],xmm3[5],xmm7[6],xmm3[6],xmm7[7],xmm3[7] +; GFNISSE-NEXT: pmullw %xmm7, %xmm8 +; GFNISSE-NEXT: psrlw $8, %xmm8 +; GFNISSE-NEXT: packuswb %xmm0, %xmm8 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: movdqa %xmm5, %xmm1 +; GFNISSE-NEXT: movdqa %xmm6, %xmm2 +; GFNISSE-NEXT: movdqa %xmm8, %xmm3 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: constant_fshl_v64i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm4[8],xmm5[9],xmm4[9],xmm5[10],xmm4[10],xmm5[11],xmm4[11],xmm5[12],xmm4[12],xmm5[13],xmm4[13],xmm5[14],xmm4[14],xmm5[15],xmm4[15] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm7 = [1,128,64,32,16,8,4,2] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm5[0],xmm4[0],xmm5[1],xmm4[1],xmm5[2],xmm4[2],xmm5[3],xmm4[3],xmm5[4],xmm4[4],xmm5[5],xmm4[5],xmm5[6],xmm4[6],xmm5[7],xmm4[7] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = [1,2,4,8,16,32,64,128] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm3, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm4[0],xmm2[0],xmm4[1],xmm2[1],xmm4[2],xmm2[2],xmm4[3],xmm2[3],xmm4[4],xmm2[4],xmm4[5],xmm2[5],xmm4[6],xmm2[6],xmm4[7],xmm2[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: constant_fshl_v64i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; GFNIAVX2-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [1,128,64,32,16,8,4,2,1,128,64,32,16,8,4,2] +; GFNIAVX2-NEXT: # ymm5 = mem[0,1,0,1] +; GFNIAVX2-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; GFNIAVX2-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128] +; GFNIAVX2-NEXT: # ymm2 = mem[0,1,0,1] +; GFNIAVX2-NEXT: vpmullw %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm3[8],ymm1[8],ymm3[9],ymm1[9],ymm3[10],ymm1[10],ymm3[11],ymm1[11],ymm3[12],ymm1[12],ymm3[13],ymm1[13],ymm3[14],ymm1[14],ymm3[15],ymm1[15],ymm3[24],ymm1[24],ymm3[25],ymm1[25],ymm3[26],ymm1[26],ymm3[27],ymm1[27],ymm3[28],ymm1[28],ymm3[29],ymm1[29],ymm3[30],ymm1[30],ymm3[31],ymm1[31] +; GFNIAVX2-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm3[0],ymm1[0],ymm3[1],ymm1[1],ymm3[2],ymm1[2],ymm3[3],ymm1[3],ymm3[4],ymm1[4],ymm3[5],ymm1[5],ymm3[6],ymm1[6],ymm3[7],ymm1[7],ymm3[16],ymm1[16],ymm3[17],ymm1[17],ymm3[18],ymm1[18],ymm3[19],ymm1[19],ymm3[20],ymm1[20],ymm3[21],ymm1[21],ymm3[22],ymm1[22],ymm3[23],ymm1[23] +; GFNIAVX2-NEXT: vpmullw %ymm2, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpackuswb %ymm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: constant_fshl_v64i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm3[8],ymm2[8],ymm3[9],ymm2[9],ymm3[10],ymm2[10],ymm3[11],ymm2[11],ymm3[12],ymm2[12],ymm3[13],ymm2[13],ymm3[14],ymm2[14],ymm3[15],ymm2[15],ymm3[24],ymm2[24],ymm3[25],ymm2[25],ymm3[26],ymm2[26],ymm3[27],ymm2[27],ymm3[28],ymm2[28],ymm3[29],ymm2[29],ymm3[30],ymm2[30],ymm3[31],ymm2[31] +; GFNIAVX512VL-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [1,128,64,32,16,8,4,2,1,128,64,32,16,8,4,2] +; GFNIAVX512VL-NEXT: # ymm5 = mem[0,1,0,1] +; GFNIAVX512VL-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm3[0],ymm2[0],ymm3[1],ymm2[1],ymm3[2],ymm2[2],ymm3[3],ymm2[3],ymm3[4],ymm2[4],ymm3[5],ymm2[5],ymm3[6],ymm2[6],ymm3[7],ymm2[7],ymm3[16],ymm2[16],ymm3[17],ymm2[17],ymm3[18],ymm2[18],ymm3[19],ymm2[19],ymm3[20],ymm2[20],ymm3[21],ymm2[21],ymm3[22],ymm2[22],ymm3[23],ymm2[23] +; GFNIAVX512VL-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128] +; GFNIAVX512VL-NEXT: # ymm3 = mem[0,1,0,1] +; GFNIAVX512VL-NEXT: vpmullw %ymm3, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpackuswb %ymm4, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpmullw %ymm3, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: constant_fshl_v64i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm2 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm2 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm2, %zmm2 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpackuswb %zmm2, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: retq + %res = call <64 x i8> @llvm.fshl.v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> ) + ret <64 x i8> %res +} + +define <64 x i8> @constant_fshr_v64i8(<64 x i8> %a, <64 x i8> %b) nounwind { +; GFNISSE-LABEL: constant_fshr_v64i8: +; GFNISSE: # %bb.0: +; GFNISSE-NEXT: movdqa %xmm4, %xmm10 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm0[8],xmm10[9],xmm0[9],xmm10[10],xmm0[10],xmm10[11],xmm0[11],xmm10[12],xmm0[12],xmm10[13],xmm0[13],xmm10[14],xmm0[14],xmm10[15],xmm0[15] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm9 = [1,128,64,32,16,8,4,2] +; GFNISSE-NEXT: pmullw %xmm9, %xmm10 +; GFNISSE-NEXT: psrlw $8, %xmm10 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; GFNISSE-NEXT: pmovzxbw {{.*#+}} xmm8 = [1,2,4,8,16,32,64,128] +; GFNISSE-NEXT: pmullw %xmm8, %xmm4 +; GFNISSE-NEXT: psrlw $8, %xmm4 +; GFNISSE-NEXT: packuswb %xmm10, %xmm4 +; GFNISSE-NEXT: movdqa %xmm5, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; GFNISSE-NEXT: pmullw %xmm9, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm1[0],xmm5[1],xmm1[1],xmm5[2],xmm1[2],xmm5[3],xmm1[3],xmm5[4],xmm1[4],xmm5[5],xmm1[5],xmm5[6],xmm1[6],xmm5[7],xmm1[7] +; GFNISSE-NEXT: pmullw %xmm8, %xmm5 +; GFNISSE-NEXT: psrlw $8, %xmm5 +; GFNISSE-NEXT: packuswb %xmm0, %xmm5 +; GFNISSE-NEXT: movdqa %xmm6, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15] +; GFNISSE-NEXT: pmullw %xmm9, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm2[0],xmm6[1],xmm2[1],xmm6[2],xmm2[2],xmm6[3],xmm2[3],xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; GFNISSE-NEXT: pmullw %xmm8, %xmm6 +; GFNISSE-NEXT: psrlw $8, %xmm6 +; GFNISSE-NEXT: packuswb %xmm0, %xmm6 +; GFNISSE-NEXT: movdqa %xmm7, %xmm0 +; GFNISSE-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15] +; GFNISSE-NEXT: pmullw %xmm9, %xmm0 +; GFNISSE-NEXT: psrlw $8, %xmm0 +; GFNISSE-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm3[0],xmm7[1],xmm3[1],xmm7[2],xmm3[2],xmm7[3],xmm3[3],xmm7[4],xmm3[4],xmm7[5],xmm3[5],xmm7[6],xmm3[6],xmm7[7],xmm3[7] +; GFNISSE-NEXT: pmullw %xmm7, %xmm8 +; GFNISSE-NEXT: psrlw $8, %xmm8 +; GFNISSE-NEXT: packuswb %xmm0, %xmm8 +; GFNISSE-NEXT: movdqa %xmm4, %xmm0 +; GFNISSE-NEXT: movdqa %xmm5, %xmm1 +; GFNISSE-NEXT: movdqa %xmm6, %xmm2 +; GFNISSE-NEXT: movdqa %xmm8, %xmm3 +; GFNISSE-NEXT: retq +; +; GFNIAVX1-LABEL: constant_fshr_v64i8: +; GFNIAVX1: # %bb.0: +; GFNIAVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm2, %xmm5 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm4[8],xmm5[9],xmm4[9],xmm5[10],xmm4[10],xmm5[11],xmm4[11],xmm5[12],xmm4[12],xmm5[13],xmm4[13],xmm5[14],xmm4[14],xmm5[15],xmm4[15] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm7 = [1,128,64,32,16,8,4,2] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm5[0],xmm4[0],xmm5[1],xmm4[1],xmm5[2],xmm4[2],xmm5[3],xmm4[3],xmm5[4],xmm4[4],xmm5[5],xmm4[5],xmm5[6],xmm4[6],xmm5[7],xmm4[7] +; GFNIAVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = [1,2,4,8,16,32,64,128] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm0, %xmm0 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; GFNIAVX1-NEXT: vextractf128 $1, %ymm3, %xmm4 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm6, %xmm6 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm4[0],xmm2[0],xmm4[1],xmm2[1],xmm4[2],xmm2[2],xmm4[3],xmm2[3],xmm4[4],xmm2[4],xmm4[5],xmm2[5],xmm4[6],xmm2[6],xmm4[7],xmm2[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpackuswb %xmm6, %xmm2, %xmm2 +; GFNIAVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] +; GFNIAVX1-NEXT: vpmullw %xmm7, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm4, %xmm4 +; GFNIAVX1-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3],xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; GFNIAVX1-NEXT: vpmullw %xmm5, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpsrlw $8, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vpackuswb %xmm4, %xmm1, %xmm1 +; GFNIAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; GFNIAVX1-NEXT: retq +; +; GFNIAVX2-LABEL: constant_fshr_v64i8: +; GFNIAVX2: # %bb.0: +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; GFNIAVX2-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [1,128,64,32,16,8,4,2,1,128,64,32,16,8,4,2] +; GFNIAVX2-NEXT: # ymm5 = mem[0,1,0,1] +; GFNIAVX2-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; GFNIAVX2-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128] +; GFNIAVX2-NEXT: # ymm2 = mem[0,1,0,1] +; GFNIAVX2-NEXT: vpmullw %ymm2, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 +; GFNIAVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm3[8],ymm1[8],ymm3[9],ymm1[9],ymm3[10],ymm1[10],ymm3[11],ymm1[11],ymm3[12],ymm1[12],ymm3[13],ymm1[13],ymm3[14],ymm1[14],ymm3[15],ymm1[15],ymm3[24],ymm1[24],ymm3[25],ymm1[25],ymm3[26],ymm1[26],ymm3[27],ymm1[27],ymm3[28],ymm1[28],ymm3[29],ymm1[29],ymm3[30],ymm1[30],ymm3[31],ymm1[31] +; GFNIAVX2-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm3[0],ymm1[0],ymm3[1],ymm1[1],ymm3[2],ymm1[2],ymm3[3],ymm1[3],ymm3[4],ymm1[4],ymm3[5],ymm1[5],ymm3[6],ymm1[6],ymm3[7],ymm1[7],ymm3[16],ymm1[16],ymm3[17],ymm1[17],ymm3[18],ymm1[18],ymm3[19],ymm1[19],ymm3[20],ymm1[20],ymm3[21],ymm1[21],ymm3[22],ymm1[22],ymm3[23],ymm1[23] +; GFNIAVX2-NEXT: vpmullw %ymm2, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpsrlw $8, %ymm1, %ymm1 +; GFNIAVX2-NEXT: vpackuswb %ymm4, %ymm1, %ymm1 +; GFNIAVX2-NEXT: retq +; +; GFNIAVX512VL-LABEL: constant_fshr_v64i8: +; GFNIAVX512VL: # %bb.0: +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; GFNIAVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm3[8],ymm2[8],ymm3[9],ymm2[9],ymm3[10],ymm2[10],ymm3[11],ymm2[11],ymm3[12],ymm2[12],ymm3[13],ymm2[13],ymm3[14],ymm2[14],ymm3[15],ymm2[15],ymm3[24],ymm2[24],ymm3[25],ymm2[25],ymm3[26],ymm2[26],ymm3[27],ymm2[27],ymm3[28],ymm2[28],ymm3[29],ymm2[29],ymm3[30],ymm2[30],ymm3[31],ymm2[31] +; GFNIAVX512VL-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [1,128,64,32,16,8,4,2,1,128,64,32,16,8,4,2] +; GFNIAVX512VL-NEXT: # ymm5 = mem[0,1,0,1] +; GFNIAVX512VL-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm3[0],ymm2[0],ymm3[1],ymm2[1],ymm3[2],ymm2[2],ymm3[3],ymm2[3],ymm3[4],ymm2[4],ymm3[5],ymm2[5],ymm3[6],ymm2[6],ymm3[7],ymm2[7],ymm3[16],ymm2[16],ymm3[17],ymm2[17],ymm3[18],ymm2[18],ymm3[19],ymm2[19],ymm3[20],ymm2[20],ymm3[21],ymm2[21],ymm3[22],ymm2[22],ymm3[23],ymm2[23] +; GFNIAVX512VL-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128] +; GFNIAVX512VL-NEXT: # ymm3 = mem[0,1,0,1] +; GFNIAVX512VL-NEXT: vpmullw %ymm3, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpackuswb %ymm4, %ymm2, %ymm2 +; GFNIAVX512VL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] +; GFNIAVX512VL-NEXT: vpmullw %ymm5, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm4, %ymm4 +; GFNIAVX512VL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; GFNIAVX512VL-NEXT: vpmullw %ymm3, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpsrlw $8, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 +; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 +; GFNIAVX512VL-NEXT: retq +; +; GFNIAVX512BW-LABEL: constant_fshr_v64i8: +; GFNIAVX512BW: # %bb.0: +; GFNIAVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm2 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm2 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm2, %zmm2 +; GFNIAVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] +; GFNIAVX512BW-NEXT: vpsllvw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpsrlw $8, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: vpackuswb %zmm2, %zmm0, %zmm0 +; GFNIAVX512BW-NEXT: retq + %res = call <64 x i8> @llvm.fshl.v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> ) + ret <64 x i8> %res +} + define <64 x i8> @splatconstant_fshl_v64i8(<64 x i8> %a, <64 x i8> %b) nounwind { ; GFNISSE-LABEL: splatconstant_fshl_v64i8: ; GFNISSE: # %bb.0: @@ -372,5 +3056,3 @@ define <64 x i8> @splatconstant_fshr_v64i8(<64 x i8> %a, <64 x i8> %b) nounwind ret <64 x i8> %res } declare <64 x i8> @llvm.fshr.v64i8(<64 x i8>, <64 x i8>, <64 x i8>) -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; GFNIAVX: {{.*}} -- GitLab From 8b2ba6a144e728ee4116e2804e9b5aed8824e726 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 22 Apr 2024 09:35:49 -0700 Subject: [PATCH 188/357] Revert "[compiler-rt][ctx_instr] Add `ctx_profile` component" (#89625) Reverts llvm/llvm-project#89304 Some build bot failures - will fix and reland. Example: https://lab.llvm.org/buildbot/#/builders/165/builds/52789 --- compiler-rt/CMakeLists.txt | 2 - .../cmake/Modules/AllSupportedArchDefs.cmake | 1 - compiler-rt/cmake/config-ix.cmake | 11 --- compiler-rt/lib/CMakeLists.txt | 4 -- compiler-rt/lib/ctx_profile/CMakeLists.txt | 28 -------- .../lib/ctx_profile/CtxInstrProfiling.cpp | 40 ----------- .../lib/ctx_profile/CtxInstrProfiling.h | 55 --------------- .../lib/ctx_profile/tests/CMakeLists.txt | 70 ------------------- .../tests/CtxInstrProfilingTest.cpp | 22 ------ compiler-rt/lib/ctx_profile/tests/driver.cpp | 14 ---- 10 files changed, 247 deletions(-) delete mode 100644 compiler-rt/lib/ctx_profile/CMakeLists.txt delete mode 100644 compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp delete mode 100644 compiler-rt/lib/ctx_profile/CtxInstrProfiling.h delete mode 100644 compiler-rt/lib/ctx_profile/tests/CMakeLists.txt delete mode 100644 compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp delete mode 100644 compiler-rt/lib/ctx_profile/tests/driver.cpp diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 6ce451e3cac2..8649507ce1c7 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -50,8 +50,6 @@ option(COMPILER_RT_BUILD_LIBFUZZER "Build libFuzzer" ON) mark_as_advanced(COMPILER_RT_BUILD_LIBFUZZER) option(COMPILER_RT_BUILD_PROFILE "Build profile runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_PROFILE) -option(COMPILER_RT_BUILD_CTX_PROFILE "Build ctx profile runtime" ON) -mark_as_advanced(COMPILER_RT_BUILD_CTX_PROFILE) option(COMPILER_RT_BUILD_MEMPROF "Build memory profiling runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_MEMPROF) option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" OFF) diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index 2fe06273a814..423171532c20 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -66,7 +66,6 @@ set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} ${RISCV32} ${RISCV64} ${LOONGARCH64}) -set(ALL_CTX_PROFILE_SUPPORTED_ARCH ${X86_64}) set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X} ${LOONGARCH64} ${RISCV64}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index ba740af9e1d6..b281ac64f5d5 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -632,9 +632,6 @@ if(APPLE) list_intersect(PROFILE_SUPPORTED_ARCH ALL_PROFILE_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_intersect(CTX_PROFILE_SUPPORTED_ARCH - ALL_CTX_PROFILE_SUPPORTED_ARCH - SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(TSAN_SUPPORTED_ARCH ALL_TSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -681,7 +678,6 @@ else() filter_available_targets(HWASAN_SUPPORTED_ARCH ${ALL_HWASAN_SUPPORTED_ARCH}) filter_available_targets(MEMPROF_SUPPORTED_ARCH ${ALL_MEMPROF_SUPPORTED_ARCH}) filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH}) - filter_available_targets(CTX_PROFILE_SUPPORTED_ARCH ${ALL_CTX_PROFILE_SUPPORTED_ARCH}) filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH}) filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH}) filter_available_targets(SAFESTACK_SUPPORTED_ARCH @@ -807,13 +803,6 @@ else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() -if (COMPILER_RT_HAS_SANITIZER_COMMON AND CTX_PROFILE_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux") - set(COMPILER_RT_HAS_CTX_PROFILE TRUE) -else() - set(COMPILER_RT_HAS_CTX_PROFILE FALSE) -endif() - if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH) if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD") set(COMPILER_RT_HAS_TSAN TRUE) diff --git a/compiler-rt/lib/CMakeLists.txt b/compiler-rt/lib/CMakeLists.txt index f9e96563b880..43ba9a102c84 100644 --- a/compiler-rt/lib/CMakeLists.txt +++ b/compiler-rt/lib/CMakeLists.txt @@ -51,10 +51,6 @@ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) compiler_rt_build_runtime(profile) endif() -if(COMPILER_RT_BUILD_CTX_PROFILE AND COMPILER_RT_HAS_CTX_PROFILE) - compiler_rt_build_runtime(ctx_profile) -endif() - if(COMPILER_RT_BUILD_XRAY) compiler_rt_build_runtime(xray) endif() diff --git a/compiler-rt/lib/ctx_profile/CMakeLists.txt b/compiler-rt/lib/ctx_profile/CMakeLists.txt deleted file mode 100644 index 621b7d30b76d..000000000000 --- a/compiler-rt/lib/ctx_profile/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -add_compiler_rt_component(ctx_profile) - -set(CTX_PROFILE_SOURCES - CtxInstrProfiling.cpp - ) - -set(CTX_PROFILE_HEADERS - CtxInstrProfiling.h - ) - -include_directories(..) -include_directories(../../include) - -# We don't use the C++ Standard Library here, so avoid including it by mistake. -append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ EXTRA_FLAGS) - -add_compiler_rt_runtime(clang_rt.ctx_profile - STATIC - ARCHS ${CTX_PROFILE_SUPPORTED_ARCH} - OBJECT_LIBS RTSanitizerCommon RTSanitizerCommonLibc - CFLAGS ${EXTRA_FLAGS} - SOURCES ${CTX_PROFILE_SOURCES} - ADDITIONAL_HEADERS ${CTX_PROFILE_HEADERS} - PARENT_TARGET ctx_profile) - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp deleted file mode 100644 index 7620ce92f7eb..000000000000 --- a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.cpp +++ /dev/null @@ -1,40 +0,0 @@ -//===- CtxInstrProfiling.cpp - contextual instrumented PGO ----------------===// -// -// 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 "CtxInstrProfiling.h" -#include "sanitizer_common/sanitizer_allocator_internal.h" -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_dense_map.h" -#include "sanitizer_common/sanitizer_mutex.h" -#include "sanitizer_common/sanitizer_placement_new.h" -#include "sanitizer_common/sanitizer_thread_safety.h" - -#include - -using namespace __ctx_profile; - -// FIXME(mtrofin): use malloc / mmap instead of sanitizer common APIs to reduce -// the dependency on the latter. -Arena *Arena::allocateNewArena(size_t Size, Arena *Prev) { - assert(!Prev || Prev->Next == nullptr); - Arena *NewArena = - new (__sanitizer::InternalAlloc(Size + sizeof(Arena))) Arena(Size); - if (Prev) - Prev->Next = NewArena; - return NewArena; -} - -void Arena::freeArenaList(Arena *&A) { - assert(A); - for (auto *I = A; I != nullptr;) { - auto *Current = I; - I = I->Next; - __sanitizer::InternalFree(Current); - } - A = nullptr; -} diff --git a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h b/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h deleted file mode 100644 index c1789c32a64c..000000000000 --- a/compiler-rt/lib/ctx_profile/CtxInstrProfiling.h +++ /dev/null @@ -1,55 +0,0 @@ -/*===- CtxInstrProfiling.h- Contextual instrumentation-based PGO ---------===*\ -|* -|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -|* See https://llvm.org/LICENSE.txt for license information. -|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef CTX_PROFILE_CTXINSTRPROFILING_H_ -#define CTX_PROFILE_CTXINSTRPROFILING_H_ - -#include - -namespace __ctx_profile { - -/// Arena (bump allocator) forming a linked list. Intentionally not thread safe. -/// Allocation and de-allocation happen using sanitizer APIs. We make that -/// explicit. -class Arena final { -public: - // When allocating a new Arena, optionally specify an existing one to append - // to, assumed to be the last in the Arena list. We only need to support - // appending to the arena list. - static Arena *allocateNewArena(size_t Size, Arena *Prev = nullptr); - static void freeArenaList(Arena *&A); - - uint64_t size() const { return Size; } - - // Allocate S bytes or return nullptr if we don't have that many available. - char *tryBumpAllocate(size_t S) { - if (Pos + S > Size) - return nullptr; - Pos += S; - return start() + (Pos - S); - } - - Arena *next() const { return Next; } - - // the beginning of allocatable memory. - const char *start() const { return const_cast(this)->start(); } - const char *pos() const { return start() + Pos; } - -private: - explicit Arena(uint32_t Size) : Size(Size) {} - ~Arena() = delete; - - char *start() { return reinterpret_cast(&this[1]); } - - Arena *Next = nullptr; - uint64_t Pos = 0; - const uint64_t Size; -}; - -} // namespace __ctx_profile -#endif // CTX_PROFILE_CTXINSTRPROFILING_H_ diff --git a/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt b/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt deleted file mode 100644 index 93b41b838445..000000000000 --- a/compiler-rt/lib/ctx_profile/tests/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -include(CheckCXXCompilerFlag) -include(CompilerRTCompile) -include(CompilerRTLink) - -set(CTX_PROFILE_UNITTEST_CFLAGS - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - ${COMPILER_RT_GMOCK_CFLAGS} - ${SANITIZER_TEST_CXX_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/lib/ - -DSANITIZER_COMMON_NO_REDEFINE_BUILTINS - -O2 - -g - -fno-rtti - -Wno-pedantic - -fno-omit-frame-pointer) - -# Suppress warnings for gmock variadic macros for clang and gcc respectively. -append_list_if(SUPPORTS_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS_FLAG -Wno-gnu-zero-variadic-macro-arguments CTX_PROFILE_UNITTEST_CFLAGS) -append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros CTX_PROFILE_UNITTEST_CFLAGS) - -file(GLOB PROFILE_HEADERS ../*.h) - -set(CTX_PROFILE_SOURCES - ../CtxInstrProfiling.cpp) - -set(CTX_PROFILE_UNITTESTS - CtxInstrProfilingTest.cpp - driver.cpp) - -include_directories(../../../include) - -set(CTX_PROFILE_UNIT_TEST_HEADERS - ${CTX_PROFILE_HEADERS}) - -set(CTX_PROFILE_UNITTEST_LINK_FLAGS - ${COMPILER_RT_UNITTEST_LINK_FLAGS}) - -list(APPEND CTX_PROFILE_UNITTEST_LINK_FLAGS -pthread) - -set(CTX_PROFILE_UNITTEST_LINK_LIBRARIES - ${COMPILER_RT_UNWINDER_LINK_LIBS} - ${SANITIZER_TEST_CXX_LIBRARIES}) -list(APPEND CTX_PROFILE_UNITTEST_LINK_LIBRARIES "dl") - -if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST CTX_PROFILE_SUPPORTED_ARCH) - # Profile unit tests are only run on the host machine. - set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) - - add_executable(CtxProfileUnitTests - ${CTX_PROFILE_UNITTESTS} - ${COMPILER_RT_GTEST_SOURCE} - ${COMPILER_RT_GMOCK_SOURCE} - ${CTX_PROFILE_SOURCES} - $ - $ - $ - $ - $) - set_target_compile_flags(CtxProfileUnitTests ${CTX_PROFILE_UNITTEST_CFLAGS}) - set_target_link_flags(CtxProfileUnitTests ${CTX_PROFILE_UNITTEST_LINK_FLAGS}) - target_link_libraries(CtxProfileUnitTests ${CTX_PROFILE_UNITTEST_LINK_LIBRARIES}) - - if (TARGET cxx-headers OR HAVE_LIBCXX) - add_dependencies(CtxProfileUnitTests cxx-headers) - endif() - - set_target_properties(CtxProfileUnitTests PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -endif() diff --git a/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp b/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp deleted file mode 100644 index 44f37d257632..000000000000 --- a/compiler-rt/lib/ctx_profile/tests/CtxInstrProfilingTest.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "../CtxInstrProfiling.h" -#include "gtest/gtest.h" - -using namespace __ctx_profile; - -TEST(ArenaTest, Basic) { - Arena *A = Arena::allocateNewArena(1024); - EXPECT_EQ(A->size(), 1024U); - EXPECT_EQ(A->next(), nullptr); - - auto *M1 = A->tryBumpAllocate(1020); - EXPECT_NE(M1, nullptr); - auto *M2 = A->tryBumpAllocate(4); - EXPECT_NE(M2, nullptr); - EXPECT_EQ(M1 + 1020, M2); - EXPECT_EQ(A->tryBumpAllocate(1), nullptr); - Arena *A2 = Arena::allocateNewArena(2024, A); - EXPECT_EQ(A->next(), A2); - EXPECT_EQ(A2->next(), nullptr); - Arena::freeArenaList(A); - EXPECT_EQ(A, nullptr); -} diff --git a/compiler-rt/lib/ctx_profile/tests/driver.cpp b/compiler-rt/lib/ctx_profile/tests/driver.cpp deleted file mode 100644 index b402cec1126b..000000000000 --- a/compiler-rt/lib/ctx_profile/tests/driver.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//===-- driver.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 "gtest/gtest.h" - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} -- GitLab From c4c54af569f7c17bc89ae73c3e5c5c4be0a586b9 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <1802579+farzonl@users.noreply.github.com> Date: Mon, 22 Apr 2024 12:40:21 -0400 Subject: [PATCH 189/357] [SPIRV][HLSL] map lerp to Fmix (#88976) - `clang/lib/CodeGen/CGBuiltin.cpp` - switch to using `getLerpIntrinsic()` to abstract backend intrinsic - `clang/lib/CodeGen/CGHLSLRuntime.h` - add `getLerpIntrinsic()` - `llvm/include/llvm/IR/IntrinsicsSPIRV.td` - add SPIRV intrinsic for lerp - `llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp` - add mapping of HLSL's lerp to GLSL's Fmix. resolves #88940 --- clang/lib/CodeGen/CGBuiltin.cpp | 4 +- clang/lib/CodeGen/CGHLSLRuntime.h | 1 + .../CodeGenHLSL/builtins/lerp-builtin.hlsl | 8 +- clang/test/CodeGenHLSL/builtins/lerp.hlsl | 96 ++++++++++++------- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 26 +++++ .../test/CodeGen/SPIRV/hlsl-intrinsics/all.ll | 76 +++++++-------- .../test/CodeGen/SPIRV/hlsl-intrinsics/any.ll | 76 +++++++-------- .../CodeGen/SPIRV/hlsl-intrinsics/lerp.ll | 56 +++++++++++ .../test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll | 66 ++++++------- 10 files changed, 260 insertions(+), 151 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/lerp.ll diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index afe2de5d00ac..7e5f2edfc732 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18267,8 +18267,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, if (!E->getArg(0)->getType()->hasFloatingRepresentation()) llvm_unreachable("lerp operand must have a float representation"); return Builder.CreateIntrinsic( - /*ReturnType=*/X->getType(), Intrinsic::dx_lerp, - ArrayRef{X, Y, S}, nullptr, "dx.lerp"); + /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(), + ArrayRef{X, Y, S}, nullptr, "hlsl.lerp"); } case Builtin::BI__builtin_hlsl_elementwise_frac: { Value *Op0 = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 506b364f5b2e..0abe39dedcb9 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -74,6 +74,7 @@ public: GENERATE_HLSL_INTRINSIC_FUNCTION(All, all) GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any) + GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp) GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id) //===----------------------------------------------------------------------===// diff --git a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl index 2fd5a19fc335..cdc9abbd70e4 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s // CHECK-LABEL: builtin_lerp_half_vector -// CHECK: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// CHECK: ret <3 x half> %dx.lerp +// CHECK: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// CHECK: ret <3 x half> %hlsl.lerp half3 builtin_lerp_half_vector (half3 p0) { return __builtin_hlsl_lerp ( p0, p0, p0 ); } // CHECK-LABEL: builtin_lerp_floar_vector -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.lerp +// CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.lerp float2 builtin_lerp_floar_vector ( float2 p0) { return __builtin_hlsl_lerp ( p0, p0, p0 ); } diff --git a/clang/test/CodeGenHLSL/builtins/lerp.hlsl b/clang/test/CodeGenHLSL/builtins/lerp.hlsl index 49cd04a10115..634b20be3a28 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp.hlsl @@ -1,69 +1,92 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: --check-prefixes=CHECK,DXIL_CHECK,DXIL_NATIVE_HALF,NATIVE_HALF // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXIL_CHECK,NO_HALF,DXIL_NO_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_NO_HALF,SPIR_CHECK -// NATIVE_HALF: %dx.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) -// NATIVE_HALF: ret half %dx.lerp -// NO_HALF: %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) -// NO_HALF: ret float %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call half @llvm.spv.lerp.f16(half %0, half %1, half %2) +// NATIVE_HALF: ret half %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) +// SPIR_NO_HALF: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) +// NO_HALF: ret float %hlsl.lerp half test_lerp_half(half p0) { return lerp(p0, p0, p0); } -// NATIVE_HALF: %dx.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) -// NATIVE_HALF: ret <2 x half> %dx.lerp -// NO_HALF: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// NO_HALF: ret <2 x float> %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <2 x half> @llvm.spv.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2) +// NATIVE_HALF: ret <2 x half> %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// SPIR_NO_HALF: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// NO_HALF: ret <2 x float> %hlsl.lerp half2 test_lerp_half2(half2 p0) { return lerp(p0, p0, p0); } -// NATIVE_HALF: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) -// NATIVE_HALF: ret <3 x half> %dx.lerp -// NO_HALF: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// NO_HALF: ret <3 x float> %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <3 x half> @llvm.spv.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) +// NATIVE_HALF: ret <3 x half> %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// SPIR_NO_HALF: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// NO_HALF: ret <3 x float> %hlsl.lerp half3 test_lerp_half3(half3 p0) { return lerp(p0, p0, p0); } -// NATIVE_HALF: %dx.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) -// NATIVE_HALF: ret <4 x half> %dx.lerp -// NO_HALF: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// NO_HALF: ret <4 x float> %dx.lerp +// DXIL_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// SPIR_NATIVE_HALF: %hlsl.lerp = call <4 x half> @llvm.spv.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) +// NATIVE_HALF: ret <4 x half> %hlsl.lerp +// DXIL_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// SPIR_NO_HALF: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// NO_HALF: ret <4 x float> %hlsl.lerp half4 test_lerp_half4(half4 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) -// CHECK: ret float %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) +// SPIR_CHECK: %hlsl.lerp = call float @llvm.spv.lerp.f32(float %0, float %1, float %2) +// CHECK: ret float %hlsl.lerp float test_lerp_float(float p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2(float2 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3(float3 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.lerp float4 test_lerp_float4(float4 p0) { return lerp(p0, p0, p0); } -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) -// CHECK: ret <2 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) +// CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2_splat(float p0, float2 p1) { return lerp(p0, p1, p1); } -// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) -// CHECK: ret <3 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2) +// CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3_splat(float p0, float3 p1) { return lerp(p0, p1, p1); } -// CHECK: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) -// CHECK: ret <4 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2) +// CHECK: ret <4 x float> %hlsl.lerp float4 test_lerp_float4_splat(float p0, float4 p1) { return lerp(p0, p1, p1); } // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) -// CHECK: ret <2 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat) +// CHECK: ret <2 x float> %hlsl.lerp float2 test_lerp_float2_int_splat(float2 p0, int p1) { return lerp(p0, p0, p1); } @@ -71,8 +94,9 @@ float2 test_lerp_float2_int_splat(float2 p0, int p1) { // CHECK: %conv = sitofp i32 %2 to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) -// CHECK: ret <3 x float> %dx.lerp +// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat) +// CHECK: ret <3 x float> %hlsl.lerp float3 test_lerp_float3_int_splat(float3 p0, int p1) { return lerp(p0, p0, p1); } diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index b6618baceb56..8660782d71d9 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -58,4 +58,6 @@ let TargetPrefix = "spv" in { Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>; def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; + def int_spv_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>], + [IntrNoMem, IntrWillReturn] >; } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 72e5a7bcac98..21a69fc3ad9b 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -170,6 +170,9 @@ private: bool selectFCmp(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; + bool selectFmix(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; + void renderImm32(MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx) const; void renderFImm32(MachineInstrBuilder &MIB, const MachineInstr &I, @@ -1242,6 +1245,27 @@ bool SPIRVInstructionSelector::selectAny(Register ResVReg, return selectAnyOrAll(ResVReg, ResType, I, SPIRV::OpAny); } +bool SPIRVInstructionSelector::selectFmix(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + + assert(I.getNumOperands() == 5); + assert(I.getOperand(2).isReg()); + assert(I.getOperand(3).isReg()); + assert(I.getOperand(4).isReg()); + MachineBasicBlock &BB = *I.getParent(); + + return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450)) + .addImm(GL::FMix) + .addUse(I.getOperand(2).getReg()) + .addUse(I.getOperand(3).getReg()) + .addUse(I.getOperand(4).getReg()) + .constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { @@ -1902,6 +1926,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectAll(ResVReg, ResType, I); case Intrinsic::spv_any: return selectAny(ResVReg, ResType, I); + case Intrinsic::spv_lerp: + return selectFmix(ResVReg, ResType, I); case Intrinsic::spv_lifetime_start: case Intrinsic::spv_lifetime_end: { unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll index ef8d463cbd81..8c5410aa54a4 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll @@ -26,32 +26,32 @@ ; CHECK-HLSL-DAG: %[[#const_i32_0:]] = OpConstant %[[#int_32]] 0 ; CHECK-HLSL-DAG: %[[#const_i16_0:]] = OpConstant %[[#int_16]] 0 ; CHECK-HLSL-DAG: %[[#const_f64_0:]] = OpConstant %[[#float_64]] 0 -; CHECK-HLSL-DAG: %[[#const_f32_0:]] = OpConstant %[[#float_32:]] 0 -; CHECK-HLSL-DAG: %[[#const_f16_0:]] = OpConstant %[[#float_16:]] 0 -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantComposite %[[#vec4_16:]] %[[#const_i16_0:]] %[[#const_i16_0:]] %[[#const_i16_0:]] %[[#const_i16_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantComposite %[[#vec4_32:]] %[[#const_i32_0:]] %[[#const_i32_0:]] %[[#const_i32_0:]] %[[#const_i32_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantComposite %[[#vec4_64:]] %[[#const_i64_0:]] %[[#const_i64_0:]] %[[#const_i64_0:]] %[[#const_i64_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantComposite %[[#vec4_float_16:]] %[[#const_f16_0:]] %[[#const_f16_0:]] %[[#const_f16_0:]] %[[#const_f16_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantComposite %[[#vec4_float_32:]] %[[#const_f32_0:]] %[[#const_f32_0:]] %[[#const_f32_0:]] %[[#const_f32_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantComposite %[[#vec4_float_64:]] %[[#const_f64_0:]] %[[#const_f64_0:]] %[[#const_f64_0:]] %[[#const_f64_0:]] +; CHECK-HLSL-DAG: %[[#const_f32_0:]] = OpConstant %[[#float_32]] 0 +; CHECK-HLSL-DAG: %[[#const_f16_0:]] = OpConstant %[[#float_16]] 0 +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantComposite %[[#vec4_16]] %[[#const_i16_0]] %[[#const_i16_0]] %[[#const_i16_0]] %[[#const_i16_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantComposite %[[#vec4_32]] %[[#const_i32_0]] %[[#const_i32_0]] %[[#const_i32_0]] %[[#const_i32_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantComposite %[[#vec4_64]] %[[#const_i64_0]] %[[#const_i64_0]] %[[#const_i64_0]] %[[#const_i64_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantComposite %[[#vec4_float_16]] %[[#const_f16_0]] %[[#const_f16_0]] %[[#const_f16_0]] %[[#const_f16_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantComposite %[[#vec4_float_32]] %[[#const_f32_0]] %[[#const_f32_0]] %[[#const_f32_0]] %[[#const_f32_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantComposite %[[#vec4_float_64]] %[[#const_f64_0]] %[[#const_f64_0]] %[[#const_f64_0]] %[[#const_f64_0]] ; CHECK-OCL-DAG: %[[#const_i64_0:]] = OpConstantNull %[[#int_64]] ; CHECK-OCL-DAG: %[[#const_i32_0:]] = OpConstantNull %[[#int_32]] ; CHECK-OCL-DAG: %[[#const_i16_0:]] = OpConstantNull %[[#int_16]] ; CHECK-OCL-DAG: %[[#const_f64_0:]] = OpConstantNull %[[#float_64]] -; CHECK-OCL-DAG: %[[#const_f32_0:]] = OpConstantNull %[[#float_32:]] -; CHECK-OCL-DAG: %[[#const_f16_0:]] = OpConstantNull %[[#float_16:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantNull %[[#vec4_16:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantNull %[[#vec4_32:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantNull %[[#vec4_64:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantNull %[[#vec4_float_16:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantNull %[[#vec4_float_32:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantNull %[[#vec4_float_64:]] +; CHECK-OCL-DAG: %[[#const_f32_0:]] = OpConstantNull %[[#float_32]] +; CHECK-OCL-DAG: %[[#const_f16_0:]] = OpConstantNull %[[#float_16]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantNull %[[#vec4_16]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantNull %[[#vec4_32]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantNull %[[#vec4_64]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantNull %[[#vec4_float_16]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantNull %[[#vec4_float_32]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantNull %[[#vec4_float_64]] define noundef i1 @all_int64_t(i64 noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpINotEqual %[[#bool:]] %[[#arg0:]] %[[#const_i64_0:]] + ; CHECK: %[[#]] = OpINotEqual %[[#bool]] %[[#arg0]] %[[#const_i64_0]] %hlsl.all = call i1 @llvm.spv.all.i64(i64 %p0) ret i1 %hlsl.all } @@ -60,7 +60,7 @@ entry: define noundef i1 @all_int(i32 noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpINotEqual %[[#bool:]] %[[#arg0:]] %[[#const_i32_0:]] + ; CHECK: %[[#]] = OpINotEqual %[[#bool]] %[[#arg0]] %[[#const_i32_0]] %hlsl.all = call i1 @llvm.spv.all.i32(i32 %p0) ret i1 %hlsl.all } @@ -69,7 +69,7 @@ entry: define noundef i1 @all_int16_t(i16 noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpINotEqual %[[#bool:]] %[[#arg0:]] %[[#const_i16_0:]] + ; CHECK: %[[#]] = OpINotEqual %[[#bool]] %[[#arg0]] %[[#const_i16_0]] %hlsl.all = call i1 @llvm.spv.all.i16(i16 %p0) ret i1 %hlsl.all } @@ -77,7 +77,7 @@ entry: define noundef i1 @all_double(double noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool:]] %[[#arg0:]] %[[#const_f64_0:]] + ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool]] %[[#arg0]] %[[#const_f64_0]] %hlsl.all = call i1 @llvm.spv.all.f64(double %p0) ret i1 %hlsl.all } @@ -86,7 +86,7 @@ entry: define noundef i1 @all_float(float noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool:]] %[[#arg0:]] %[[#const_f32_0:]] + ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool]] %[[#arg0]] %[[#const_f32_0]] %hlsl.all = call i1 @llvm.spv.all.f32(float %p0) ret i1 %hlsl.all } @@ -95,7 +95,7 @@ entry: define noundef i1 @all_half(half noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool:]] %[[#arg0:]] %[[#const_f16_0:]] + ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool]] %[[#arg0]] %[[#const_f16_0]] %hlsl.all = call i1 @llvm.spv.all.f16(half %p0) ret i1 %hlsl.all } @@ -103,8 +103,8 @@ entry: define noundef i1 @all_bool4(<4 x i1> noundef %p0) { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpAll %[[#vec4_bool:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_bool]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#arg0]] %hlsl.all = call i1 @llvm.spv.all.v4i1(<4 x i1> %p0) ret i1 %hlsl.all } @@ -112,8 +112,8 @@ entry: define noundef i1 @all_short4(<4 x i16> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#shortVecNotEq:]] = OpINotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_i16:]] - ; CHECK: %[[#]] = OpAll %[[#bool:]] %[[#shortVecNotEq:]] + ; CHECK: %[[#shortVecNotEq:]] = OpINotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_i16]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#shortVecNotEq]] %hlsl.all = call i1 @llvm.spv.all.v4i16(<4 x i16> %p0) ret i1 %hlsl.all } @@ -121,8 +121,8 @@ entry: define noundef i1 @all_int4(<4 x i32> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#i32VecNotEq:]] = OpINotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_i32:]] - ; CHECK: %[[#]] = OpAll %[[#bool:]] %[[#i32VecNotEq:]] + ; CHECK: %[[#i32VecNotEq:]] = OpINotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_i32]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#i32VecNotEq]] %hlsl.all = call i1 @llvm.spv.all.v4i32(<4 x i32> %p0) ret i1 %hlsl.all } @@ -130,8 +130,8 @@ entry: define noundef i1 @all_int64_t4(<4 x i64> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#i64VecNotEq:]] = OpINotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_i64:]] - ; CHECK: %[[#]] = OpAll %[[#bool:]] %[[#i64VecNotEq]] + ; CHECK: %[[#i64VecNotEq:]] = OpINotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_i64]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#i64VecNotEq]] %hlsl.all = call i1 @llvm.spv.all.v4i64(<4 x i64> %p0) ret i1 %hlsl.all } @@ -139,8 +139,8 @@ entry: define noundef i1 @all_half4(<4 x half> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#f16VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_f16:]] - ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#f16VecNotEq:]] + ; CHECK: %[[#f16VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_f16]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#f16VecNotEq]] %hlsl.all = call i1 @llvm.spv.all.v4f16(<4 x half> %p0) ret i1 %hlsl.all } @@ -148,8 +148,8 @@ entry: define noundef i1 @all_float4(<4 x float> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#f32VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_f32:]] - ; CHECK: %[[#]] = OpAll %[[#bool:]] %[[#f32VecNotEq:]] + ; CHECK: %[[#f32VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_f32]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#f32VecNotEq]] %hlsl.all = call i1 @llvm.spv.all.v4f32(<4 x float> %p0) ret i1 %hlsl.all } @@ -157,16 +157,16 @@ entry: define noundef i1 @all_double4(<4 x double> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#f64VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_f64:]] - ; CHECK: %[[#]] = OpAll %[[#bool:]] %[[#f64VecNotEq:]] + ; CHECK: %[[#f64VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_f64]] + ; CHECK: %[[#]] = OpAll %[[#bool]] %[[#f64VecNotEq]] %hlsl.all = call i1 @llvm.spv.all.v4f64(<4 x double> %p0) ret i1 %hlsl.all } define noundef i1 @all_bool(i1 noundef %a) { entry: - ; CHECK: %[[#all_bool_arg:]] = OpFunctionParameter %[[#bool:]] - ; CHECK: OpReturnValue %[[#all_bool_arg:]] + ; CHECK: %[[#all_bool_arg:]] = OpFunctionParameter %[[#bool]] + ; CHECK: OpReturnValue %[[#all_bool_arg]] %hlsl.all = call i1 @llvm.spv.all.i1(i1 %a) ret i1 %hlsl.all } diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/any.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/any.ll index b1dd388f5c6e..7a74a335a659 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/any.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/any.ll @@ -26,32 +26,32 @@ ; CHECK-HLSL-DAG: %[[#const_i32_0:]] = OpConstant %[[#int_32]] 0 ; CHECK-HLSL-DAG: %[[#const_i16_0:]] = OpConstant %[[#int_16]] 0 ; CHECK-HLSL-DAG: %[[#const_f64_0:]] = OpConstant %[[#float_64]] 0 -; CHECK-HLSL-DAG: %[[#const_f32_0:]] = OpConstant %[[#float_32:]] 0 -; CHECK-HLSL-DAG: %[[#const_f16_0:]] = OpConstant %[[#float_16:]] 0 -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantComposite %[[#vec4_16:]] %[[#const_i16_0:]] %[[#const_i16_0:]] %[[#const_i16_0:]] %[[#const_i16_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantComposite %[[#vec4_32:]] %[[#const_i32_0:]] %[[#const_i32_0:]] %[[#const_i32_0:]] %[[#const_i32_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantComposite %[[#vec4_64:]] %[[#const_i64_0:]] %[[#const_i64_0:]] %[[#const_i64_0:]] %[[#const_i64_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantComposite %[[#vec4_float_16:]] %[[#const_f16_0:]] %[[#const_f16_0:]] %[[#const_f16_0:]] %[[#const_f16_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantComposite %[[#vec4_float_32:]] %[[#const_f32_0:]] %[[#const_f32_0:]] %[[#const_f32_0:]] %[[#const_f32_0:]] -; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantComposite %[[#vec4_float_64:]] %[[#const_f64_0:]] %[[#const_f64_0:]] %[[#const_f64_0:]] %[[#const_f64_0:]] +; CHECK-HLSL-DAG: %[[#const_f32_0:]] = OpConstant %[[#float_32]] 0 +; CHECK-HLSL-DAG: %[[#const_f16_0:]] = OpConstant %[[#float_16]] 0 +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantComposite %[[#vec4_16]] %[[#const_i16_0]] %[[#const_i16_0]] %[[#const_i16_0]] %[[#const_i16_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantComposite %[[#vec4_32]] %[[#const_i32_0]] %[[#const_i32_0]] %[[#const_i32_0]] %[[#const_i32_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantComposite %[[#vec4_64]] %[[#const_i64_0]] %[[#const_i64_0]] %[[#const_i64_0]] %[[#const_i64_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantComposite %[[#vec4_float_16]] %[[#const_f16_0]] %[[#const_f16_0]] %[[#const_f16_0]] %[[#const_f16_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantComposite %[[#vec4_float_32]] %[[#const_f32_0]] %[[#const_f32_0]] %[[#const_f32_0]] %[[#const_f32_0]] +; CHECK-HLSL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantComposite %[[#vec4_float_64]] %[[#const_f64_0]] %[[#const_f64_0]] %[[#const_f64_0]] %[[#const_f64_0]] ; CHECK-OCL-DAG: %[[#const_i64_0:]] = OpConstantNull %[[#int_64]] ; CHECK-OCL-DAG: %[[#const_i32_0:]] = OpConstantNull %[[#int_32]] ; CHECK-OCL-DAG: %[[#const_i16_0:]] = OpConstantNull %[[#int_16]] ; CHECK-OCL-DAG: %[[#const_f64_0:]] = OpConstantNull %[[#float_64]] -; CHECK-OCL-DAG: %[[#const_f32_0:]] = OpConstantNull %[[#float_32:]] -; CHECK-OCL-DAG: %[[#const_f16_0:]] = OpConstantNull %[[#float_16:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantNull %[[#vec4_16:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantNull %[[#vec4_32:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantNull %[[#vec4_64:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantNull %[[#vec4_float_16:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantNull %[[#vec4_float_32:]] -; CHECK-OCL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantNull %[[#vec4_float_64:]] +; CHECK-OCL-DAG: %[[#const_f32_0:]] = OpConstantNull %[[#float_32]] +; CHECK-OCL-DAG: %[[#const_f16_0:]] = OpConstantNull %[[#float_16]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_i16:]] = OpConstantNull %[[#vec4_16]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_i32:]] = OpConstantNull %[[#vec4_32]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_i64:]] = OpConstantNull %[[#vec4_64]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_f16:]] = OpConstantNull %[[#vec4_float_16]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_f32:]] = OpConstantNull %[[#vec4_float_32]] +; CHECK-OCL-DAG: %[[#vec4_const_zeros_f64:]] = OpConstantNull %[[#vec4_float_64]] define noundef i1 @any_int64_t(i64 noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpINotEqual %[[#bool:]] %[[#arg0:]] %[[#const_i64_0:]] + ; CHECK: %[[#]] = OpINotEqual %[[#bool]] %[[#arg0]] %[[#const_i64_0]] %hlsl.any = call i1 @llvm.spv.any.i64(i64 %p0) ret i1 %hlsl.any } @@ -60,7 +60,7 @@ entry: define noundef i1 @any_int(i32 noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpINotEqual %[[#bool:]] %[[#arg0:]] %[[#const_i32_0:]] + ; CHECK: %[[#]] = OpINotEqual %[[#bool]] %[[#arg0]] %[[#const_i32_0]] %hlsl.any = call i1 @llvm.spv.any.i32(i32 %p0) ret i1 %hlsl.any } @@ -69,7 +69,7 @@ entry: define noundef i1 @any_int16_t(i16 noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpINotEqual %[[#bool:]] %[[#arg0:]] %[[#const_i16_0:]] + ; CHECK: %[[#]] = OpINotEqual %[[#bool]] %[[#arg0]] %[[#const_i16_0]] %hlsl.any = call i1 @llvm.spv.any.i16(i16 %p0) ret i1 %hlsl.any } @@ -77,7 +77,7 @@ entry: define noundef i1 @any_double(double noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool:]] %[[#arg0:]] %[[#const_f64_0:]] + ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool]] %[[#arg0]] %[[#const_f64_0]] %hlsl.any = call i1 @llvm.spv.any.f64(double %p0) ret i1 %hlsl.any } @@ -86,7 +86,7 @@ entry: define noundef i1 @any_float(float noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool:]] %[[#arg0:]] %[[#const_f32_0:]] + ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool]] %[[#arg0]] %[[#const_f32_0]] %hlsl.any = call i1 @llvm.spv.any.f32(float %p0) ret i1 %hlsl.any } @@ -95,7 +95,7 @@ entry: define noundef i1 @any_half(half noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool:]] %[[#arg0:]] %[[#const_f16_0:]] + ; CHECK: %[[#]] = OpFOrdNotEqual %[[#bool]] %[[#arg0]] %[[#const_f16_0]] %hlsl.any = call i1 @llvm.spv.any.f16(half %p0) ret i1 %hlsl.any } @@ -103,8 +103,8 @@ entry: define noundef i1 @any_bool4(<4 x i1> noundef %p0) { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#]] = OpAny %[[#vec4_bool:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_bool]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#arg0]] %hlsl.any = call i1 @llvm.spv.any.v4i1(<4 x i1> %p0) ret i1 %hlsl.any } @@ -112,8 +112,8 @@ entry: define noundef i1 @any_short4(<4 x i16> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#shortVecNotEq:]] = OpINotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_i16:]] - ; CHECK: %[[#]] = OpAny %[[#bool:]] %[[#shortVecNotEq:]] + ; CHECK: %[[#shortVecNotEq:]] = OpINotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_i16]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#shortVecNotEq]] %hlsl.any = call i1 @llvm.spv.any.v4i16(<4 x i16> %p0) ret i1 %hlsl.any } @@ -121,8 +121,8 @@ entry: define noundef i1 @any_int4(<4 x i32> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#i32VecNotEq:]] = OpINotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_i32:]] - ; CHECK: %[[#]] = OpAny %[[#bool:]] %[[#i32VecNotEq:]] + ; CHECK: %[[#i32VecNotEq:]] = OpINotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_i32]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#i32VecNotEq]] %hlsl.any = call i1 @llvm.spv.any.v4i32(<4 x i32> %p0) ret i1 %hlsl.any } @@ -130,8 +130,8 @@ entry: define noundef i1 @any_int64_t4(<4 x i64> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#i64VecNotEq:]] = OpINotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_i64:]] - ; CHECK: %[[#]] = OpAny %[[#bool:]] %[[#i64VecNotEq]] + ; CHECK: %[[#i64VecNotEq:]] = OpINotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_i64]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#i64VecNotEq]] %hlsl.any = call i1 @llvm.spv.any.v4i64(<4 x i64> %p0) ret i1 %hlsl.any } @@ -139,8 +139,8 @@ entry: define noundef i1 @any_half4(<4 x half> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#f16VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_f16:]] - ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#f16VecNotEq:]] + ; CHECK: %[[#f16VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_f16]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#f16VecNotEq]] %hlsl.any = call i1 @llvm.spv.any.v4f16(<4 x half> %p0) ret i1 %hlsl.any } @@ -148,8 +148,8 @@ entry: define noundef i1 @any_float4(<4 x float> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#f32VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_f32:]] - ; CHECK: %[[#]] = OpAny %[[#bool:]] %[[#f32VecNotEq:]] + ; CHECK: %[[#f32VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_f32]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#f32VecNotEq]] %hlsl.any = call i1 @llvm.spv.any.v4f32(<4 x float> %p0) ret i1 %hlsl.any } @@ -157,16 +157,16 @@ entry: define noundef i1 @any_double4(<4 x double> noundef %p0) { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] - ; CHECK: %[[#f64VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool:]] %[[#arg0:]] %[[#vec4_const_zeros_f64:]] - ; CHECK: %[[#]] = OpAny %[[#bool:]] %[[#f64VecNotEq:]] + ; CHECK: %[[#f64VecNotEq:]] = OpFOrdNotEqual %[[#vec4_bool]] %[[#arg0]] %[[#vec4_const_zeros_f64]] + ; CHECK: %[[#]] = OpAny %[[#bool]] %[[#f64VecNotEq]] %hlsl.any = call i1 @llvm.spv.any.v4f64(<4 x double> %p0) ret i1 %hlsl.any } define noundef i1 @any_bool(i1 noundef %a) { entry: - ; CHECK: %[[#any_bool_arg:]] = OpFunctionParameter %[[#bool:]] - ; CHECK: OpReturnValue %[[#any_bool_arg:]] + ; CHECK: %[[#any_bool_arg:]] = OpFunctionParameter %[[#bool]] + ; CHECK: OpReturnValue %[[#any_bool_arg]] %hlsl.any = call i1 @llvm.spv.any.i1(i1 %a) ret i1 %hlsl.any } diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/lerp.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/lerp.ll new file mode 100644 index 000000000000..63547820c18c --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/lerp.ll @@ -0,0 +1,56 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; Make sure SPIRV operation function calls for lerp are generated as FMix + +; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450" +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 +; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 + +define noundef half @lerp_half(half noundef %a, half noundef %b, half noundef %c) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] FMix %[[#arg0]] %[[#arg1]] %[[#arg2]] + %hlsl.lerp = call half @llvm.spv.lerp.f16(half %a, half %b, half %c) + ret half %hlsl.lerp +} + + +define noundef float @lerp_float(float noundef %a, float noundef %b, float noundef %c) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] FMix %[[#arg0]] %[[#arg1]] %[[#arg2]] + %hlsl.lerp = call float @llvm.spv.lerp.f32(float %a, float %b, float %c) + ret float %hlsl.lerp +} + +define noundef <4 x half> @lerp_half4(<4 x half> noundef %a, <4 x half> noundef %b, <4 x half> noundef %c) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] FMix %[[#arg0]] %[[#arg1]] %[[#arg2]] + %hlsl.lerp = call <4 x half> @llvm.spv.lerp.v4f16(<4 x half> %a, <4 x half> %b, <4 x half> %c) + ret <4 x half> %hlsl.lerp +} + +define noundef <4 x float> @lerp_float4(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c) { +entry: + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] FMix %[[#arg0]] %[[#arg1]] %[[#arg2]] + %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) + ret <4 x float> %hlsl.lerp +} + +declare half @llvm.spv.lerp.f16(half, half, half) +declare float @llvm.spv.lerp.f32(float, float, float) +declare <4 x half> @llvm.spv.lerp.v4f16(<4 x half>, <4 x half>, <4 x half>) +declare <4 x float> @llvm.spv.lerp.v4f32(<4 x float>, <4 x float>, <4 x float>) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll index 95962c0fdc96..34f3c610ca81 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/rcp.ll @@ -13,90 +13,90 @@ ; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 ; CHECK-DAG: %[[#vec4_float_64:]] = OpTypeVector %[[#float_64]] 4 ; CHECK-DAG: %[[#const_f64_1:]] = OpConstant %[[#float_64]] 1 -; CHECK-DAG: %[[#const_f32_1:]] = OpConstant %[[#float_32:]] 1 -; CHECK-DAG: %[[#const_f16_1:]] = OpConstant %[[#float_16:]] 1 +; CHECK-DAG: %[[#const_f32_1:]] = OpConstant %[[#float_32]] 1 +; CHECK-DAG: %[[#const_f16_1:]] = OpConstant %[[#float_16]] 1 -; CHECK-DAG: %[[#vec2_const_ones_f16:]] = OpConstantComposite %[[#vec2_float_16:]] %[[#const_f16_1:]] %[[#const_f16_1:]] -; CHECK-DAG: %[[#vec3_const_ones_f16:]] = OpConstantComposite %[[#vec3_float_16:]] %[[#const_f16_1:]] %[[#const_f16_1:]] %[[#const_f16_1:]] -; CHECK-DAG: %[[#vec4_const_ones_f16:]] = OpConstantComposite %[[#vec4_float_16:]] %[[#const_f16_1:]] %[[#const_f16_1:]] %[[#const_f16_1:]] %[[#const_f16_1:]] +; CHECK-DAG: %[[#vec2_const_ones_f16:]] = OpConstantComposite %[[#vec2_float_16]] %[[#const_f16_1]] %[[#const_f16_1]] +; CHECK-DAG: %[[#vec3_const_ones_f16:]] = OpConstantComposite %[[#vec3_float_16]] %[[#const_f16_1]] %[[#const_f16_1]] %[[#const_f16_1]] +; CHECK-DAG: %[[#vec4_const_ones_f16:]] = OpConstantComposite %[[#vec4_float_16]] %[[#const_f16_1]] %[[#const_f16_1]] %[[#const_f16_1]] %[[#const_f16_1]] -; CHECK-DAG: %[[#vec2_const_ones_f32:]] = OpConstantComposite %[[#vec2_float_32:]] %[[#const_f32_1:]] %[[#const_f32_1:]] -; CHECK-DAG: %[[#vec3_const_ones_f32:]] = OpConstantComposite %[[#vec3_float_32:]] %[[#const_f32_1:]] %[[#const_f32_1:]] %[[#const_f32_1:]] -; CHECK-DAG: %[[#vec4_const_ones_f32:]] = OpConstantComposite %[[#vec4_float_32:]] %[[#const_f32_1:]] %[[#const_f32_1:]] %[[#const_f32_1:]] %[[#const_f32_1:]] +; CHECK-DAG: %[[#vec2_const_ones_f32:]] = OpConstantComposite %[[#vec2_float_32]] %[[#const_f32_1]] %[[#const_f32_1]] +; CHECK-DAG: %[[#vec3_const_ones_f32:]] = OpConstantComposite %[[#vec3_float_32]] %[[#const_f32_1]] %[[#const_f32_1]] %[[#const_f32_1]] +; CHECK-DAG: %[[#vec4_const_ones_f32:]] = OpConstantComposite %[[#vec4_float_32]] %[[#const_f32_1]] %[[#const_f32_1]] %[[#const_f32_1]] %[[#const_f32_1]] -; CHECK-DAG: %[[#vec2_const_ones_f64:]] = OpConstantComposite %[[#vec2_float_64:]] %[[#const_f64_1:]] %[[#const_f64_1:]] -; CHECK-DAG: %[[#vec3_const_ones_f64:]] = OpConstantComposite %[[#vec3_float_64:]] %[[#const_f64_1:]] %[[#const_f64_1:]] %[[#const_f64_1:]] -; CHECK-DAG: %[[#vec4_const_ones_f64:]] = OpConstantComposite %[[#vec4_float_64:]] %[[#const_f64_1:]] %[[#const_f64_1:]] %[[#const_f64_1:]] %[[#const_f64_1:]] +; CHECK-DAG: %[[#vec2_const_ones_f64:]] = OpConstantComposite %[[#vec2_float_64]] %[[#const_f64_1]] %[[#const_f64_1]] +; CHECK-DAG: %[[#vec3_const_ones_f64:]] = OpConstantComposite %[[#vec3_float_64]] %[[#const_f64_1]] %[[#const_f64_1]] %[[#const_f64_1]] +; CHECK-DAG: %[[#vec4_const_ones_f64:]] = OpConstantComposite %[[#vec4_float_64]] %[[#const_f64_1]] %[[#const_f64_1]] %[[#const_f64_1]] %[[#const_f64_1]] define spir_func noundef half @test_rcp_half(half noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16:]] - ; CHECK: OpFDiv %[[#float_16:]] %[[#const_f16_1:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]] + ; CHECK: OpFDiv %[[#float_16]] %[[#const_f16_1]] %[[#arg0]] %hlsl.rcp = fdiv half 0xH3C00, %p0 ret half %hlsl.rcp } define spir_func noundef <2 x half> @test_rcp_half2(<2 x half> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_16:]] - ; CHECK: OpFDiv %[[#vec2_float_16:]] %[[#vec2_const_ones_f16:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_16]] + ; CHECK: OpFDiv %[[#vec2_float_16]] %[[#vec2_const_ones_f16]] %[[#arg0]] %hlsl.rcp = fdiv <2 x half> , %p0 ret <2 x half> %hlsl.rcp } define spir_func noundef <3 x half> @test_rcp_half3(<3 x half> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_16:]] - ; CHECK: OpFDiv %[[#vec3_float_16:]] %[[#vec3_const_ones_f16:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_16]] + ; CHECK: OpFDiv %[[#vec3_float_16]] %[[#vec3_const_ones_f16]] %[[#arg0]] %hlsl.rcp = fdiv <3 x half> , %p0 ret <3 x half> %hlsl.rcp } define spir_func noundef <4 x half> @test_rcp_half4(<4 x half> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16:]] - ; CHECK: OpFDiv %[[#vec4_float_16:]] %[[#vec4_const_ones_f16:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: OpFDiv %[[#vec4_float_16]] %[[#vec4_const_ones_f16]] %[[#arg0]] %hlsl.rcp = fdiv <4 x half> , %p0 ret <4 x half> %hlsl.rcp } define spir_func noundef float @test_rcp_float(float noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32:]] - ; CHECK: OpFDiv %[[#float_32:]] %[[#const_f32_1:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]] + ; CHECK: OpFDiv %[[#float_32]] %[[#const_f32_1]] %[[#arg0]] %hlsl.rcp = fdiv float 1.000000e+00, %p0 ret float %hlsl.rcp } define spir_func noundef <2 x float> @test_rcp_float2(<2 x float> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_32:]] - ; CHECK: OpFDiv %[[#vec2_float_32:]] %[[#vec2_const_ones_f32:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_32]] + ; CHECK: OpFDiv %[[#vec2_float_32]] %[[#vec2_const_ones_f32]] %[[#arg0]] %hlsl.rcp = fdiv <2 x float> , %p0 ret <2 x float> %hlsl.rcp } define spir_func noundef <3 x float> @test_rcp_float3(<3 x float> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_32:]] - ; CHECK: OpFDiv %[[#vec3_float_32:]] %[[#vec3_const_ones_f32:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_32]] + ; CHECK: OpFDiv %[[#vec3_float_32]] %[[#vec3_const_ones_f32]] %[[#arg0]] %hlsl.rcp = fdiv <3 x float> , %p0 ret <3 x float> %hlsl.rcp } define spir_func noundef <4 x float> @test_rcp_float4(<4 x float> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32:]] - ; CHECK: OpFDiv %[[#vec4_float_32:]] %[[#vec4_const_ones_f32:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: OpFDiv %[[#vec4_float_32]] %[[#vec4_const_ones_f32]] %[[#arg0]] %hlsl.rcp = fdiv <4 x float> , %p0 ret <4 x float> %hlsl.rcp } define spir_func noundef double @test_rcp_double(double noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_64:]] - ; CHECK: OpFDiv %[[#float_64:]] %[[#const_f64_1:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_64]] + ; CHECK: OpFDiv %[[#float_64]] %[[#const_f64_1]] %[[#arg0]] %hlsl.rcp = fdiv double 1.000000e+00, %p0 ret double %hlsl.rcp } @@ -104,7 +104,7 @@ entry: define spir_func noundef <2 x double> @test_rcp_double2(<2 x double> noundef %p0) #0 { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec2_float_64:]] - ; CHECK: OpFDiv %[[#vec2_float_64:]] %[[#vec2_const_ones_f64:]] %[[#arg0:]] + ; CHECK: OpFDiv %[[#vec2_float_64]] %[[#vec2_const_ones_f64]] %[[#arg0]] %hlsl.rcp = fdiv <2 x double> , %p0 ret <2 x double> %hlsl.rcp } @@ -112,15 +112,15 @@ entry: define spir_func noundef <3 x double> @test_rcp_double3(<3 x double> noundef %p0) #0 { entry: ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_64:]] - ; CHECK: OpFDiv %[[#vec3_float_64:]] %[[#vec3_const_ones_f64:]] %[[#arg0:]] + ; CHECK: OpFDiv %[[#vec3_float_64]] %[[#vec3_const_ones_f64]] %[[#arg0]] %hlsl.rcp = fdiv <3 x double> , %p0 ret <3 x double> %hlsl.rcp } define spir_func noundef <4 x double> @test_rcp_double4(<4 x double> noundef %p0) #0 { entry: - ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_64:]] - ; CHECK: OpFDiv %[[#vec4_float_64:]] %[[#vec4_const_ones_f64:]] %[[#arg0:]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_64]] + ; CHECK: OpFDiv %[[#vec4_float_64]] %[[#vec4_const_ones_f64]] %[[#arg0]] %hlsl.rcp = fdiv <4 x double> , %p0 ret <4 x double> %hlsl.rcp } -- GitLab From b6628c24ef017138b8d6eb288e94c141e7c846b0 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Mon, 22 Apr 2024 18:41:36 +0200 Subject: [PATCH 190/357] [Clang] Fix crash on invalid size in user-defined `static_assert` message (#89420) This addresses two problems observed in #89407 wrt user-defined `static_assert` messages: 1. In `Expr::EvaluateCharRangeAsString`, we were calling `getExtValue()` instead of `getZExtValue()`, which would assert if a negative or very large number was returned from `size()`. 2. If the value could not be converted to `std::size_t`, attempting to diagnose that would crash because `ext_cce_narrowing` was missing two `%select` cases. This fixes #89407. --- clang/docs/ReleaseNotes.rst | 2 + .../clang/Basic/DiagnosticSemaKinds.td | 6 +- clang/lib/AST/ExprConstant.cpp | 4 +- clang/test/SemaCXX/static-assert-cxx26.cpp | 74 +++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 009531bae8a9..aea99680c79a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -555,6 +555,8 @@ Bug Fixes to C++ Support - Fix a crash caused by defined struct in a type alias template when the structure has fields with dependent type. Fixes (#GH75221). - Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906) +- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()`` + function returns a large or negative value. Fixes (#GH89407). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a95424862e63..63e951daec74 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -87,9 +87,9 @@ def err_expr_not_cce : Error< "call to 'size()'|call to 'data()'}0 is not a constant expression">; def ext_cce_narrowing : ExtWarn< "%select{case value|enumerator value|non-type template argument|" - "array size|explicit specifier argument|noexcept specifier argument}0 " - "%select{cannot be narrowed from type %2 to %3|" - "evaluates to %2, which cannot be narrowed to type %3}1">, + "array size|explicit specifier argument|noexcept specifier argument|" + "call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from " + "type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">, InGroup, DefaultError, SFINAEFailure; def err_ice_not_integral : Error< "%select{integer|integral}1 constant expression must have " diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 73ae8d8efb23..de3c2a63913e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -16853,13 +16853,13 @@ bool Expr::EvaluateCharRangeAsString(std::string &Result, if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) return false; - int64_t Size = SizeValue.getExtValue(); + uint64_t Size = SizeValue.getZExtValue(); if (!::EvaluatePointer(PtrExpression, String, Info)) return false; QualType CharTy = PtrExpression->getType()->getPointeeType(); - for (int64_t I = 0; I < Size; ++I) { + for (uint64_t I = 0; I < Size; ++I) { APValue Char; if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, Char)) diff --git a/clang/test/SemaCXX/static-assert-cxx26.cpp b/clang/test/SemaCXX/static-assert-cxx26.cpp index f4ede74f9214..7d896d8b365b 100644 --- a/clang/test/SemaCXX/static-assert-cxx26.cpp +++ b/clang/test/SemaCXX/static-assert-cxx26.cpp @@ -341,3 +341,77 @@ struct Callable { } data; }; static_assert(false, Callable{}); // expected-error {{static assertion failed: hello}} + +namespace GH89407 { +struct A { + constexpr __SIZE_TYPE__ size() const { return -1; } + constexpr const char* data() const { return ""; } +}; + +struct B { + constexpr long long size() const { return 18446744073709551615U; } + constexpr const char* data() const { return ""; } +}; + +struct C { + constexpr __int128 size() const { return -1; } + constexpr const char* data() const { return ""; } +}; + +struct D { + constexpr unsigned __int128 size() const { return -1; } + constexpr const char* data() const { return ""; } +}; + +struct E { + constexpr __SIZE_TYPE__ size() const { return 18446744073709551615U; } + constexpr const char* data() const { return ""; } +}; + +static_assert(true, A{}); // expected-error {{the message in this static assertion is not a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, B{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in this static assertion is not a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, C{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in this static assertion is not a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, D{}); // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in this static assertion is not a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +static_assert(true, E{}); // expected-error {{the message in this static assertion is not a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} + +static_assert( + false, // expected-error {{static assertion failed}} + A{} // expected-error {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + B{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + C{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + D{} // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}} + // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); + +static_assert( + false, // expected-error {{static assertion failed}} + E{} // expected-error {{the message in a static assertion must be produced by a constant expression}} + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +); +} -- GitLab From 330d8983d25d08580fc1642fea48b2473f47a9da Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 22 Apr 2024 09:51:33 -0700 Subject: [PATCH 191/357] [Offload] Move `/openmp/libomptarget` to `/offload` (#75125) In a nutshell, this moves our libomptarget code to populate the offload subproject. With this commit, users need to enable the new LLVM/Offload subproject as a runtime in their cmake configuration. No further changes are expected for downstream code. Tests and other components still depend on OpenMP and have also not been renamed. The results below are for a build in which OpenMP and Offload are enabled runtimes. In addition to the pure `git mv`, we needed to adjust some CMake files. Nothing is intended to change semantics. ``` ninja check-offload ``` Works with the X86 and AMDGPU offload tests ``` ninja check-openmp ``` Still works but doesn't build offload tests anymore. ``` ls install/lib ``` Shows all expected libraries, incl. - `libomptarget.devicertl.a` - `libomptarget-nvptx-sm_90.bc` - `libomptarget.rtl.amdgpu.so` -> `libomptarget.rtl.amdgpu.so.18git` - `libomptarget.so` -> `libomptarget.so.18git` Fixes: https://github.com/llvm/llvm-project/issues/75124 --------- Co-authored-by: Saiyedul Islam --- llvm/CMakeLists.txt | 2 +- .../libomptarget => offload}/CMakeLists.txt | 166 +++++++++++- .../DeviceRTL/CMakeLists.txt | 4 +- .../DeviceRTL/include/Allocator.h | 0 .../DeviceRTL/include/Configuration.h | 0 .../DeviceRTL/include/Debug.h | 0 .../DeviceRTL/include/Interface.h | 0 .../DeviceRTL/include/LibC.h | 0 .../DeviceRTL/include/Mapping.h | 0 .../DeviceRTL/include/State.h | 0 .../DeviceRTL/include/Synchronization.h | 0 .../DeviceRTL/include/Types.h | 0 .../DeviceRTL/include/Utils.h | 0 .../include/generated_microtask_cases.gen | 0 .../DeviceRTL/src/Allocator.cpp | 0 .../DeviceRTL/src/Configuration.cpp | 0 .../DeviceRTL/src/Debug.cpp | 0 .../DeviceRTL/src/Kernel.cpp | 0 .../DeviceRTL/src/LibC.cpp | 0 .../DeviceRTL/src/Mapping.cpp | 0 .../DeviceRTL/src/Misc.cpp | 0 .../DeviceRTL/src/Parallelism.cpp | 0 .../DeviceRTL/src/Reduction.cpp | 0 .../DeviceRTL/src/State.cpp | 0 .../DeviceRTL/src/Stub.cpp | 0 .../DeviceRTL/src/Synchronization.cpp | 0 .../DeviceRTL/src/Tasking.cpp | 0 .../DeviceRTL/src/Utils.cpp | 0 .../DeviceRTL/src/Workshare.cpp | 0 .../DeviceRTL/src/exports | 0 {openmp/libomptarget => offload}/README.txt | 0 .../Modules/LibomptargetGetDependencies.cmake | 0 .../cmake/Modules/LibomptargetUtils.cmake | 0 offload/cmake/OpenMPTesting.cmake | 238 ++++++++++++++++++ .../docs/declare_target_indirect.md | 0 .../include/DeviceImage.h | 0 .../include/ExclusiveAccess.h | 0 .../include/OffloadEntry.h | 0 .../include/OffloadPolicy.h | 0 .../include/OpenMP/InternalTypes.h | 0 .../include/OpenMP/InteropAPI.h | 0 .../include/OpenMP/Mapping.h | 0 .../include/OpenMP/OMPT/Callback.h | 0 .../include/OpenMP/OMPT/Connector.h | 0 .../include/OpenMP/OMPT/Interface.h | 0 .../include/OpenMP/omp.h | 0 .../include/PluginManager.h | 0 .../include/Shared/APITypes.h | 0 .../include/Shared/Debug.h | 0 .../include/Shared/Environment.h | 0 .../include/Shared/EnvironmentVar.h | 0 .../include/Shared/PluginAPI.h | 0 .../include/Shared/PluginAPI.inc | 0 .../include/Shared/Profile.h | 0 .../include/Shared/Requirements.h | 0 .../include/Shared/SourceInfo.h | 0 .../include/Shared/Utils.h | 0 .../include/Utils/ExponentialBackoff.h | 0 .../libomptarget => offload}/include/device.h | 0 .../include/omptarget.h | 0 .../libomptarget => offload}/include/rtl.h | 0 .../plugins-nextgen/CMakeLists.txt | 0 .../plugins-nextgen/amdgpu/CMakeLists.txt | 2 +- .../amdgpu/dynamic_hsa/hsa.cpp | 0 .../plugins-nextgen/amdgpu/dynamic_hsa/hsa.h | 0 .../amdgpu/dynamic_hsa/hsa_ext_amd.h | 0 .../plugins-nextgen/amdgpu/src/rtl.cpp | 0 .../amdgpu/utils/UtilitiesRTL.h | 0 .../plugins-nextgen/common/CMakeLists.txt | 0 .../common/OMPT/OmptCallback.cpp | 0 .../plugins-nextgen/common/include/DLWrap.h | 0 .../common/include/GlobalHandler.h | 0 .../plugins-nextgen/common/include/JIT.h | 0 .../common/include/MemoryManager.h | 0 .../common/include/PluginInterface.h | 0 .../plugins-nextgen/common/include/RPC.h | 0 .../common/include/Utils/ELF.h | 0 .../common/src/GlobalHandler.cpp | 0 .../plugins-nextgen/common/src/JIT.cpp | 0 .../common/src/PluginInterface.cpp | 0 .../plugins-nextgen/common/src/RPC.cpp | 0 .../plugins-nextgen/common/src/Utils/ELF.cpp | 0 .../plugins-nextgen/cuda/CMakeLists.txt | 2 +- .../cuda/dynamic_cuda/cuda.cpp | 0 .../plugins-nextgen/cuda/dynamic_cuda/cuda.h | 0 .../plugins-nextgen/cuda/src/rtl.cpp | 0 .../plugins-nextgen/exports | 0 .../plugins-nextgen/host/CMakeLists.txt | 2 +- .../plugins-nextgen/host/dynamic_ffi/ffi.cpp | 0 .../plugins-nextgen/host/dynamic_ffi/ffi.h | 0 .../plugins-nextgen/host/src/rtl.cpp | 0 .../src/CMakeLists.txt | 10 +- .../src/DeviceImage.cpp | 0 .../src/LegacyAPI.cpp | 0 .../src/OffloadRTL.cpp | 0 .../src/OpenMP/API.cpp | 0 .../src/OpenMP/InteropAPI.cpp | 0 .../src/OpenMP/Mapping.cpp | 0 .../src/OpenMP/OMPT/Callback.cpp | 0 .../src/PluginManager.cpp | 0 .../libomptarget => offload}/src/device.cpp | 0 {openmp/libomptarget => offload}/src/exports | 0 .../src/interface.cpp | 0 .../src/omptarget.cpp | 0 .../libomptarget => offload}/src/private.h | 0 .../test/CMakeLists.txt | 15 +- .../test/Inputs/basic_array.f90 | 0 .../test/Inputs/declare_indirect_func.c | 0 .../test/api/assert.c | 0 .../test/api/is_initial_device.c | 0 .../test/api/omp_device_managed_memory.c | 0 .../api/omp_device_managed_memory_alloc.c | 0 .../test/api/omp_device_memory.c | 0 .../test/api/omp_dynamic_shared_memory.c | 0 .../api/omp_dynamic_shared_memory_amdgpu.c | 0 .../api/omp_dynamic_shared_memory_mixed.inc | 0 .../omp_dynamic_shared_memory_mixed_amdgpu.c | 0 .../omp_dynamic_shared_memory_mixed_nvptx.c | 0 .../test/api/omp_env_vars.c | 0 .../test/api/omp_get_device_num.c | 0 .../test/api/omp_get_mapped_ptr.c | 0 .../test/api/omp_get_num_devices.c | 0 .../omp_get_num_devices_with_empty_target.c | 0 .../test/api/omp_get_num_procs.c | 0 .../test/api/omp_host_pinned_memory.c | 0 .../test/api/omp_host_pinned_memory_alloc.c | 0 .../test/api/omp_indirect_call.c | 0 .../test/api/omp_target_memcpy_async1.c | 0 .../test/api/omp_target_memcpy_async2.c | 0 .../test/api/omp_target_memcpy_rect_async1.c | 0 .../test/api/omp_target_memcpy_rect_async2.c | 0 .../test/api/omp_target_memset.c | 0 .../test/api/ompx_3d.c | 0 .../test/api/ompx_3d.cpp | 0 .../test/api/ompx_sync.c | 0 .../test/api/ompx_sync.cpp | 0 .../test/env/base_ptr_ref_count.c | 0 .../test/env/omp_target_debug.c | 0 .../test/jit/empty_kernel.inc | 0 .../test/jit/empty_kernel_lvl1.c | 0 .../test/jit/empty_kernel_lvl2.c | 0 .../test/jit/type_punning.c | 0 .../test/libc/assert.c | 0 .../test/libc/fwrite.c | 0 .../test/libc/global_ctor_dtor.cpp | 0 .../test/libc/host_call.c | 0 .../test/libc/malloc.c | 0 .../libomptarget => offload}/test/libc/puts.c | 0 {openmp/libomptarget => offload}/test/lit.cfg | 0 .../test/lit.site.cfg.in | 0 .../test/mapping/alloc_fail.c | 0 .../mapping/array_section_implicit_capture.c | 0 .../mapping/array_section_use_device_ptr.c | 0 .../test/mapping/auto_zero_copy.cpp | 0 .../test/mapping/auto_zero_copy_apu.cpp | 0 .../test/mapping/auto_zero_copy_globals.cpp | 0 .../test/mapping/data_absent_at_exit.c | 0 .../test/mapping/data_member_ref.cpp | 0 .../test/mapping/declare_mapper_api.cpp | 0 .../declare_mapper_nested_default_mappers.cpp | 0 ...re_mapper_nested_default_mappers_array.cpp | 0 ...nested_default_mappers_array_subscript.cpp | 0 ...sted_default_mappers_complex_structure.cpp | 0 ...r_nested_default_mappers_ptr_subscript.cpp | 0 ...lare_mapper_nested_default_mappers_var.cpp | 0 .../mapping/declare_mapper_nested_mappers.cpp | 0 .../test/mapping/declare_mapper_target.cpp | 0 .../mapping/declare_mapper_target_data.cpp | 0 .../declare_mapper_target_data_enter_exit.cpp | 0 .../mapping/declare_mapper_target_update.cpp | 0 .../test/mapping/delete_inf_refcount.c | 0 .../test/mapping/device_ptr_update.c | 0 .../test/mapping/firstprivate_aligned.cpp | 0 .../test/mapping/has_device_addr.cpp | 0 .../test/mapping/implicit_device_ptr.c | 0 .../test/mapping/is_device_ptr.cpp | 0 .../test/mapping/lambda_by_value.cpp | 0 .../test/mapping/lambda_mapping.cpp | 0 .../test/mapping/low_alignment.c | 0 .../test/mapping/map_back_race.cpp | 0 .../ompx_hold/omp_target_disassociate_ptr.c | 0 .../test/mapping/ompx_hold/struct.c | 0 .../test/mapping/ompx_hold/target-data.c | 0 .../test/mapping/ompx_hold/target.c | 0 .../test/mapping/padding_not_mapped.c | 0 .../test/mapping/power_of_two_alignment.c | 0 .../test/mapping/pr38704.c | 0 .../test/mapping/prelock.cpp | 0 .../test/mapping/present/target.c | 0 .../mapping/present/target_array_extension.c | 0 .../test/mapping/present/target_data.c | 0 .../present/target_data_array_extension.c | 0 .../mapping/present/target_data_at_exit.c | 0 .../test/mapping/present/target_enter_data.c | 0 .../mapping/present/target_exit_data_delete.c | 0 .../present/target_exit_data_release.c | 0 .../test/mapping/present/target_update.c | 0 .../present/target_update_array_extension.c | 0 .../mapping/present/unified_shared_memory.c | 0 .../present/zero_length_array_section.c | 0 .../present/zero_length_array_section_exit.c | 0 .../test/mapping/private_mapping.c | 0 .../test/mapping/ptr_and_obj_motion.c | 0 .../test/mapping/reduction_implicit_map.cpp | 0 .../target_data_array_extension_at_exit.c | 0 .../target_derefence_array_pointrs.cpp | 0 .../test/mapping/target_has_device_addr.c | 0 .../mapping/target_implicit_partial_map.c | 0 .../mapping/target_map_for_member_data.cpp | 0 .../mapping/target_pointers_members_map.cpp | 0 .../mapping/target_update_array_extension.c | 0 .../test/mapping/target_use_device_addr.c | 0 .../test/mapping/target_uses_allocator.c | 0 .../mapping/target_wrong_use_device_addr.c | 0 .../test/offloading/assert.cpp | 0 .../offloading/atomic-compare-signedness.c | 0 .../test/offloading/back2back_distribute.c | 0 .../test/offloading/barrier_fence.c | 0 .../test/offloading/bug47654.cpp | 0 .../test/offloading/bug49021.cpp | 0 .../test/offloading/bug49334.cpp | 0 .../test/offloading/bug49779.cpp | 0 .../test/offloading/bug50022.cpp | 0 .../test/offloading/bug51781.c | 0 .../test/offloading/bug51982.c | 0 .../test/offloading/bug53727.cpp | 0 .../test/offloading/bug64959.c | 0 .../test/offloading/bug64959_compile_only.c | 0 .../test/offloading/bug74582.c | 0 .../test/offloading/complex_reduction.cpp | 0 .../test/offloading/ctor_dtor.cpp | 0 .../test/offloading/cuda_no_devices.c | 0 .../test/offloading/d2d_memcpy.c | 0 .../test/offloading/d2d_memcpy_sync.c | 0 .../test/offloading/default_thread_limit.c | 0 .../test/offloading/dynamic_module.c | 0 .../test/offloading/dynamic_module_load.c | 0 .../test/offloading/extern.c | 0 .../test/offloading/force-usm.cpp | 0 .../fortran/basic-target-parallel-do.f90 | 0 .../fortran/basic-target-parallel-region.f90 | 0 .../basic-target-region-1D-array-section.f90 | 0 .../basic-target-region-3D-array-section.f90 | 0 .../fortran/basic-target-region-3D-array.f90 | 0 .../test/offloading/fortran/basic_array.c | 0 .../fortran/basic_target_region.f90 | 0 .../offloading/fortran/constant-arr-index.f90 | 0 .../declare-target-vars-in-target-region.f90 | 0 ...double-target-call-with-declare-target.f90 | 0 ...ap-allocatable-array-section-1d-bounds.f90 | 0 ...ap-allocatable-array-section-3d-bounds.f90 | 0 .../target-map-allocatable-map-scopes.f90 | 0 .../target-map-enter-exit-allocatables.f90 | 0 .../fortran/target-map-enter-exit-array-2.f90 | 0 .../target-map-enter-exit-array-bounds.f90 | 0 .../fortran/target-map-enter-exit-array.f90 | 0 .../fortran/target-map-enter-exit-scalar.f90 | 0 .../target-map-pointer-scopes-enter-exit.f90 | 0 ...pointer-target-array-section-3d-bounds.f90 | 0 .../target-map-pointer-target-scopes.f90 | 0 .../fortran/target-nested-target-data.f90 | 0 .../fortran/target-parallel-do-collapse.f90 | 0 .../fortran/target-region-implicit-array.f90 | 0 .../fortran/target_map_common_block.f90 | 0 .../fortran/target_map_common_block1.f90 | 0 .../fortran/target_map_common_block2.f90 | 0 .../test/offloading/fortran/target_update.f90 | 0 .../generic_multiple_parallel_regions.c | 0 .../test/offloading/global_constructor.cpp | 0 .../test/offloading/host_as_target.c | 0 .../test/offloading/indirect_fp_mapping.c | 0 .../test/offloading/info.c | 0 .../test/offloading/interop.c | 0 .../test/offloading/lone_target_exit_data.c | 0 .../test/offloading/looptripcnt.c | 0 .../test/offloading/malloc.c | 0 .../test/offloading/malloc_parallel.c | 0 .../offloading/mandatory_but_no_devices.c | 0 .../test/offloading/memory_manager.cpp | 0 .../offloading/multiple_reductions_simple.c | 0 .../test/offloading/non_contiguous_update.cpp | 0 .../test/offloading/offloading_success.c | 0 .../test/offloading/offloading_success.cpp | 0 .../test/offloading/ompx_bare.c | 0 .../test/offloading/ompx_coords.c | 0 .../test/offloading/ompx_saxpy_mixed.c | 0 .../offloading/parallel_offloading_map.cpp | 0 .../parallel_target_teams_reduction.cpp | 0 .../parallel_target_teams_reduction_max.cpp | 0 .../parallel_target_teams_reduction_min.cpp | 0 .../test/offloading/requires.c | 0 .../test/offloading/runtime_init.c | 0 .../test/offloading/shared_lib_fp_mapping.c | 0 .../test/offloading/small_trip_count.c | 0 .../small_trip_count_thread_limit.cpp | 0 .../test/offloading/spmdization.c | 0 .../test/offloading/static_linking.c | 0 .../offloading/std_complex_arithmetic.cpp | 0 .../struct_mapping_with_pointers.cpp | 0 .../test/offloading/target-teams-atomic.c | 0 .../test/offloading/target-tile.c | 0 .../offloading/target_constexpr_mapping.cpp | 0 .../offloading/target_critical_region.cpp | 0 .../test/offloading/target_depend_nowait.cpp | 0 .../offloading/target_map_for_member_data.cpp | 0 .../test/offloading/target_nowait_target.cpp | 0 .../offloading/task_in_reduction_target.c | 0 .../offloading/taskloop_offload_nowait.cpp | 0 .../test/offloading/test_libc.cpp | 0 .../test/offloading/thread_limit.c | 0 .../test/offloading/thread_state_1.c | 0 .../test/offloading/thread_state_2.c | 0 .../test/offloading/weak.c | 0 .../test/offloading/workshare_chunk.c | 0 .../test/offloading/wtime.c | 0 .../test/ompt/callbacks.h | 0 .../test/ompt/register_both.h | 0 .../test/ompt/register_emi.h | 0 .../test/ompt/register_emi_map.h | 0 .../test/ompt/register_no_device_init.h | 0 .../test/ompt/register_non_emi.h | 0 .../test/ompt/register_non_emi_map.h | 0 .../test/ompt/register_wrong_return.h | 0 .../test/ompt/target_memcpy.c | 0 .../test/ompt/target_memcpy_emi.c | 0 .../test/ompt/veccopy.c | 0 .../test/ompt/veccopy_data.c | 0 .../test/ompt/veccopy_disallow_both.c | 0 .../test/ompt/veccopy_emi.c | 0 .../test/ompt/veccopy_emi_map.c | 0 .../test/ompt/veccopy_map.c | 0 .../test/ompt/veccopy_no_device_init.c | 0 .../test/ompt/veccopy_wrong_return.c | 0 .../test/unified_shared_memory/api.c | 0 .../unified_shared_memory/associate_ptr.c | 0 .../unified_shared_memory/close_enter_exit.c | 0 .../test/unified_shared_memory/close_manual.c | 0 .../test/unified_shared_memory/close_member.c | 0 .../unified_shared_memory/close_modifier.c | 0 .../unified_shared_memory/shared_update.c | 0 .../tools/CMakeLists.txt | 0 .../tools/deviceinfo/CMakeLists.txt | 0 .../tools/deviceinfo/llvm-omp-device-info.cpp | 0 .../tools/kernelreplay/CMakeLists.txt | 0 .../kernelreplay/llvm-omp-kernel-replay.cpp | 0 .../unittests/CMakeLists.txt | 0 .../unittests/Plugins/CMakeLists.txt | 0 .../unittests/Plugins/NextgenPluginsTest.cpp | 0 .../utils/generate_microtask_cases.py | 0 openmp/CMakeLists.txt | 29 +-- .../test/api/ompx_dump_mapping_tables.cpp | 35 --- openmp/runtime/src/CMakeLists.txt | 8 +- runtimes/CMakeLists.txt | 2 +- 353 files changed, 442 insertions(+), 73 deletions(-) rename {openmp/libomptarget => offload}/CMakeLists.txt (56%) rename {openmp/libomptarget => offload}/DeviceRTL/CMakeLists.txt (99%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Allocator.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Configuration.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Debug.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Interface.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/LibC.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Mapping.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/State.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Synchronization.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Types.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/Utils.h (100%) rename {openmp/libomptarget => offload}/DeviceRTL/include/generated_microtask_cases.gen (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Allocator.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Configuration.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Debug.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Kernel.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/LibC.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Mapping.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Misc.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Parallelism.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Reduction.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/State.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Stub.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Synchronization.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Tasking.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Utils.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/Workshare.cpp (100%) rename {openmp/libomptarget => offload}/DeviceRTL/src/exports (100%) rename {openmp/libomptarget => offload}/README.txt (100%) rename {openmp/libomptarget => offload}/cmake/Modules/LibomptargetGetDependencies.cmake (100%) rename {openmp/libomptarget => offload}/cmake/Modules/LibomptargetUtils.cmake (100%) create mode 100644 offload/cmake/OpenMPTesting.cmake rename {openmp/libomptarget => offload}/docs/declare_target_indirect.md (100%) rename {openmp/libomptarget => offload}/include/DeviceImage.h (100%) rename {openmp/libomptarget => offload}/include/ExclusiveAccess.h (100%) rename {openmp/libomptarget => offload}/include/OffloadEntry.h (100%) rename {openmp/libomptarget => offload}/include/OffloadPolicy.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/InternalTypes.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/InteropAPI.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/Mapping.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/OMPT/Callback.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/OMPT/Connector.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/OMPT/Interface.h (100%) rename {openmp/libomptarget => offload}/include/OpenMP/omp.h (100%) rename {openmp/libomptarget => offload}/include/PluginManager.h (100%) rename {openmp/libomptarget => offload}/include/Shared/APITypes.h (100%) rename {openmp/libomptarget => offload}/include/Shared/Debug.h (100%) rename {openmp/libomptarget => offload}/include/Shared/Environment.h (100%) rename {openmp/libomptarget => offload}/include/Shared/EnvironmentVar.h (100%) rename {openmp/libomptarget => offload}/include/Shared/PluginAPI.h (100%) rename {openmp/libomptarget => offload}/include/Shared/PluginAPI.inc (100%) rename {openmp/libomptarget => offload}/include/Shared/Profile.h (100%) rename {openmp/libomptarget => offload}/include/Shared/Requirements.h (100%) rename {openmp/libomptarget => offload}/include/Shared/SourceInfo.h (100%) rename {openmp/libomptarget => offload}/include/Shared/Utils.h (100%) rename {openmp/libomptarget => offload}/include/Utils/ExponentialBackoff.h (100%) rename {openmp/libomptarget => offload}/include/device.h (100%) rename {openmp/libomptarget => offload}/include/omptarget.h (100%) rename {openmp/libomptarget => offload}/include/rtl.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/amdgpu/CMakeLists.txt (97%) rename {openmp/libomptarget => offload}/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/amdgpu/dynamic_hsa/hsa_ext_amd.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/amdgpu/src/rtl.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/OMPT/OmptCallback.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/DLWrap.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/GlobalHandler.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/JIT.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/MemoryManager.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/PluginInterface.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/RPC.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/include/Utils/ELF.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/src/GlobalHandler.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/src/JIT.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/src/PluginInterface.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/src/RPC.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/common/src/Utils/ELF.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/cuda/CMakeLists.txt (96%) rename {openmp/libomptarget => offload}/plugins-nextgen/cuda/dynamic_cuda/cuda.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/cuda/dynamic_cuda/cuda.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/cuda/src/rtl.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/exports (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/host/CMakeLists.txt (98%) rename {openmp/libomptarget => offload}/plugins-nextgen/host/dynamic_ffi/ffi.cpp (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/host/dynamic_ffi/ffi.h (100%) rename {openmp/libomptarget => offload}/plugins-nextgen/host/src/rtl.cpp (100%) rename {openmp/libomptarget => offload}/src/CMakeLists.txt (95%) rename {openmp/libomptarget => offload}/src/DeviceImage.cpp (100%) rename {openmp/libomptarget => offload}/src/LegacyAPI.cpp (100%) rename {openmp/libomptarget => offload}/src/OffloadRTL.cpp (100%) rename {openmp/libomptarget => offload}/src/OpenMP/API.cpp (100%) rename {openmp/libomptarget => offload}/src/OpenMP/InteropAPI.cpp (100%) rename {openmp/libomptarget => offload}/src/OpenMP/Mapping.cpp (100%) rename {openmp/libomptarget => offload}/src/OpenMP/OMPT/Callback.cpp (100%) rename {openmp/libomptarget => offload}/src/PluginManager.cpp (100%) rename {openmp/libomptarget => offload}/src/device.cpp (100%) rename {openmp/libomptarget => offload}/src/exports (100%) rename {openmp/libomptarget => offload}/src/interface.cpp (100%) rename {openmp/libomptarget => offload}/src/omptarget.cpp (100%) rename {openmp/libomptarget => offload}/src/private.h (100%) rename {openmp/libomptarget => offload}/test/CMakeLists.txt (78%) rename {openmp/libomptarget => offload}/test/Inputs/basic_array.f90 (100%) rename {openmp/libomptarget => offload}/test/Inputs/declare_indirect_func.c (100%) rename {openmp/libomptarget => offload}/test/api/assert.c (100%) rename {openmp/libomptarget => offload}/test/api/is_initial_device.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_device_managed_memory.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_device_managed_memory_alloc.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_device_memory.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_dynamic_shared_memory.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_dynamic_shared_memory_amdgpu.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_dynamic_shared_memory_mixed.inc (100%) rename {openmp/libomptarget => offload}/test/api/omp_dynamic_shared_memory_mixed_amdgpu.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_dynamic_shared_memory_mixed_nvptx.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_env_vars.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_get_device_num.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_get_mapped_ptr.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_get_num_devices.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_get_num_devices_with_empty_target.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_get_num_procs.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_host_pinned_memory.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_host_pinned_memory_alloc.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_indirect_call.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_target_memcpy_async1.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_target_memcpy_async2.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_target_memcpy_rect_async1.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_target_memcpy_rect_async2.c (100%) rename {openmp/libomptarget => offload}/test/api/omp_target_memset.c (100%) rename {openmp/libomptarget => offload}/test/api/ompx_3d.c (100%) rename {openmp/libomptarget => offload}/test/api/ompx_3d.cpp (100%) rename {openmp/libomptarget => offload}/test/api/ompx_sync.c (100%) rename {openmp/libomptarget => offload}/test/api/ompx_sync.cpp (100%) rename {openmp/libomptarget => offload}/test/env/base_ptr_ref_count.c (100%) rename {openmp/libomptarget => offload}/test/env/omp_target_debug.c (100%) rename {openmp/libomptarget => offload}/test/jit/empty_kernel.inc (100%) rename {openmp/libomptarget => offload}/test/jit/empty_kernel_lvl1.c (100%) rename {openmp/libomptarget => offload}/test/jit/empty_kernel_lvl2.c (100%) rename {openmp/libomptarget => offload}/test/jit/type_punning.c (100%) rename {openmp/libomptarget => offload}/test/libc/assert.c (100%) rename {openmp/libomptarget => offload}/test/libc/fwrite.c (100%) rename {openmp/libomptarget => offload}/test/libc/global_ctor_dtor.cpp (100%) rename {openmp/libomptarget => offload}/test/libc/host_call.c (100%) rename {openmp/libomptarget => offload}/test/libc/malloc.c (100%) rename {openmp/libomptarget => offload}/test/libc/puts.c (100%) rename {openmp/libomptarget => offload}/test/lit.cfg (100%) rename {openmp/libomptarget => offload}/test/lit.site.cfg.in (100%) rename {openmp/libomptarget => offload}/test/mapping/alloc_fail.c (100%) rename {openmp/libomptarget => offload}/test/mapping/array_section_implicit_capture.c (100%) rename {openmp/libomptarget => offload}/test/mapping/array_section_use_device_ptr.c (100%) rename {openmp/libomptarget => offload}/test/mapping/auto_zero_copy.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/auto_zero_copy_apu.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/auto_zero_copy_globals.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/data_absent_at_exit.c (100%) rename {openmp/libomptarget => offload}/test/mapping/data_member_ref.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_api.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_default_mappers.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_default_mappers_array.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_default_mappers_array_subscript.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_default_mappers_complex_structure.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_default_mappers_ptr_subscript.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_default_mappers_var.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_nested_mappers.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_target.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_target_data.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_target_data_enter_exit.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/declare_mapper_target_update.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/delete_inf_refcount.c (100%) rename {openmp/libomptarget => offload}/test/mapping/device_ptr_update.c (100%) rename {openmp/libomptarget => offload}/test/mapping/firstprivate_aligned.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/has_device_addr.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/implicit_device_ptr.c (100%) rename {openmp/libomptarget => offload}/test/mapping/is_device_ptr.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/lambda_by_value.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/lambda_mapping.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/low_alignment.c (100%) rename {openmp/libomptarget => offload}/test/mapping/map_back_race.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/ompx_hold/omp_target_disassociate_ptr.c (100%) rename {openmp/libomptarget => offload}/test/mapping/ompx_hold/struct.c (100%) rename {openmp/libomptarget => offload}/test/mapping/ompx_hold/target-data.c (100%) rename {openmp/libomptarget => offload}/test/mapping/ompx_hold/target.c (100%) rename {openmp/libomptarget => offload}/test/mapping/padding_not_mapped.c (100%) rename {openmp/libomptarget => offload}/test/mapping/power_of_two_alignment.c (100%) rename {openmp/libomptarget => offload}/test/mapping/pr38704.c (100%) rename {openmp/libomptarget => offload}/test/mapping/prelock.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_array_extension.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_data.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_data_array_extension.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_data_at_exit.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_enter_data.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_exit_data_delete.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_exit_data_release.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_update.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/target_update_array_extension.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/unified_shared_memory.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/zero_length_array_section.c (100%) rename {openmp/libomptarget => offload}/test/mapping/present/zero_length_array_section_exit.c (100%) rename {openmp/libomptarget => offload}/test/mapping/private_mapping.c (100%) rename {openmp/libomptarget => offload}/test/mapping/ptr_and_obj_motion.c (100%) rename {openmp/libomptarget => offload}/test/mapping/reduction_implicit_map.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/target_data_array_extension_at_exit.c (100%) rename {openmp/libomptarget => offload}/test/mapping/target_derefence_array_pointrs.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/target_has_device_addr.c (100%) rename {openmp/libomptarget => offload}/test/mapping/target_implicit_partial_map.c (100%) rename {openmp/libomptarget => offload}/test/mapping/target_map_for_member_data.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/target_pointers_members_map.cpp (100%) rename {openmp/libomptarget => offload}/test/mapping/target_update_array_extension.c (100%) rename {openmp/libomptarget => offload}/test/mapping/target_use_device_addr.c (100%) rename {openmp/libomptarget => offload}/test/mapping/target_uses_allocator.c (100%) rename {openmp/libomptarget => offload}/test/mapping/target_wrong_use_device_addr.c (100%) rename {openmp/libomptarget => offload}/test/offloading/assert.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/atomic-compare-signedness.c (100%) rename {openmp/libomptarget => offload}/test/offloading/back2back_distribute.c (100%) rename {openmp/libomptarget => offload}/test/offloading/barrier_fence.c (100%) rename {openmp/libomptarget => offload}/test/offloading/bug47654.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/bug49021.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/bug49334.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/bug49779.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/bug50022.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/bug51781.c (100%) rename {openmp/libomptarget => offload}/test/offloading/bug51982.c (100%) rename {openmp/libomptarget => offload}/test/offloading/bug53727.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/bug64959.c (100%) rename {openmp/libomptarget => offload}/test/offloading/bug64959_compile_only.c (100%) rename {openmp/libomptarget => offload}/test/offloading/bug74582.c (100%) rename {openmp/libomptarget => offload}/test/offloading/complex_reduction.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/ctor_dtor.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/cuda_no_devices.c (100%) rename {openmp/libomptarget => offload}/test/offloading/d2d_memcpy.c (100%) rename {openmp/libomptarget => offload}/test/offloading/d2d_memcpy_sync.c (100%) rename {openmp/libomptarget => offload}/test/offloading/default_thread_limit.c (100%) rename {openmp/libomptarget => offload}/test/offloading/dynamic_module.c (100%) rename {openmp/libomptarget => offload}/test/offloading/dynamic_module_load.c (100%) rename {openmp/libomptarget => offload}/test/offloading/extern.c (100%) rename {openmp/libomptarget => offload}/test/offloading/force-usm.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic-target-parallel-do.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic-target-parallel-region.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic-target-region-1D-array-section.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic-target-region-3D-array-section.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic-target-region-3D-array.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic_array.c (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/basic_target_region.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/constant-arr-index.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/declare-target-vars-in-target-region.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/double-target-call-with-declare-target.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-allocatable-array-section-1d-bounds.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-allocatable-array-section-3d-bounds.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-allocatable-map-scopes.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-enter-exit-allocatables.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-enter-exit-array-2.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-enter-exit-array.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-enter-exit-scalar.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-pointer-scopes-enter-exit.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-pointer-target-array-section-3d-bounds.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-map-pointer-target-scopes.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-nested-target-data.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-parallel-do-collapse.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target-region-implicit-array.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target_map_common_block.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target_map_common_block1.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target_map_common_block2.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/fortran/target_update.f90 (100%) rename {openmp/libomptarget => offload}/test/offloading/generic_multiple_parallel_regions.c (100%) rename {openmp/libomptarget => offload}/test/offloading/global_constructor.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/host_as_target.c (100%) rename {openmp/libomptarget => offload}/test/offloading/indirect_fp_mapping.c (100%) rename {openmp/libomptarget => offload}/test/offloading/info.c (100%) rename {openmp/libomptarget => offload}/test/offloading/interop.c (100%) rename {openmp/libomptarget => offload}/test/offloading/lone_target_exit_data.c (100%) rename {openmp/libomptarget => offload}/test/offloading/looptripcnt.c (100%) rename {openmp/libomptarget => offload}/test/offloading/malloc.c (100%) rename {openmp/libomptarget => offload}/test/offloading/malloc_parallel.c (100%) rename {openmp/libomptarget => offload}/test/offloading/mandatory_but_no_devices.c (100%) rename {openmp/libomptarget => offload}/test/offloading/memory_manager.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/multiple_reductions_simple.c (100%) rename {openmp/libomptarget => offload}/test/offloading/non_contiguous_update.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/offloading_success.c (100%) rename {openmp/libomptarget => offload}/test/offloading/offloading_success.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/ompx_bare.c (100%) rename {openmp/libomptarget => offload}/test/offloading/ompx_coords.c (100%) rename {openmp/libomptarget => offload}/test/offloading/ompx_saxpy_mixed.c (100%) rename {openmp/libomptarget => offload}/test/offloading/parallel_offloading_map.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/parallel_target_teams_reduction.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/parallel_target_teams_reduction_max.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/parallel_target_teams_reduction_min.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/requires.c (100%) rename {openmp/libomptarget => offload}/test/offloading/runtime_init.c (100%) rename {openmp/libomptarget => offload}/test/offloading/shared_lib_fp_mapping.c (100%) rename {openmp/libomptarget => offload}/test/offloading/small_trip_count.c (100%) rename {openmp/libomptarget => offload}/test/offloading/small_trip_count_thread_limit.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/spmdization.c (100%) rename {openmp/libomptarget => offload}/test/offloading/static_linking.c (100%) rename {openmp/libomptarget => offload}/test/offloading/std_complex_arithmetic.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/struct_mapping_with_pointers.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/target-teams-atomic.c (100%) rename {openmp/libomptarget => offload}/test/offloading/target-tile.c (100%) rename {openmp/libomptarget => offload}/test/offloading/target_constexpr_mapping.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/target_critical_region.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/target_depend_nowait.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/target_map_for_member_data.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/target_nowait_target.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/task_in_reduction_target.c (100%) rename {openmp/libomptarget => offload}/test/offloading/taskloop_offload_nowait.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/test_libc.cpp (100%) rename {openmp/libomptarget => offload}/test/offloading/thread_limit.c (100%) rename {openmp/libomptarget => offload}/test/offloading/thread_state_1.c (100%) rename {openmp/libomptarget => offload}/test/offloading/thread_state_2.c (100%) rename {openmp/libomptarget => offload}/test/offloading/weak.c (100%) rename {openmp/libomptarget => offload}/test/offloading/workshare_chunk.c (100%) rename {openmp/libomptarget => offload}/test/offloading/wtime.c (100%) rename {openmp/libomptarget => offload}/test/ompt/callbacks.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_both.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_emi.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_emi_map.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_no_device_init.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_non_emi.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_non_emi_map.h (100%) rename {openmp/libomptarget => offload}/test/ompt/register_wrong_return.h (100%) rename {openmp/libomptarget => offload}/test/ompt/target_memcpy.c (100%) rename {openmp/libomptarget => offload}/test/ompt/target_memcpy_emi.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_data.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_disallow_both.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_emi.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_emi_map.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_map.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_no_device_init.c (100%) rename {openmp/libomptarget => offload}/test/ompt/veccopy_wrong_return.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/api.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/associate_ptr.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/close_enter_exit.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/close_manual.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/close_member.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/close_modifier.c (100%) rename {openmp/libomptarget => offload}/test/unified_shared_memory/shared_update.c (100%) rename {openmp/libomptarget => offload}/tools/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/tools/deviceinfo/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/tools/deviceinfo/llvm-omp-device-info.cpp (100%) rename {openmp/libomptarget => offload}/tools/kernelreplay/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/tools/kernelreplay/llvm-omp-kernel-replay.cpp (100%) rename {openmp/libomptarget => offload}/unittests/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/unittests/Plugins/CMakeLists.txt (100%) rename {openmp/libomptarget => offload}/unittests/Plugins/NextgenPluginsTest.cpp (100%) rename {openmp/libomptarget => offload}/utils/generate_microtask_cases.py (100%) delete mode 100644 openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index d511376e18ba..43181af3bc19 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -147,7 +147,7 @@ endif() # As we migrate runtimes to using the bootstrapping build, the set of default runtimes # should grow as we remove those runtimes from LLVM_ENABLE_PROJECTS above. set(LLVM_DEFAULT_RUNTIMES "libcxx;libcxxabi;libunwind") -set(LLVM_SUPPORTED_RUNTIMES "libc;libunwind;libcxxabi;pstl;libcxx;compiler-rt;openmp;llvm-libgcc") +set(LLVM_SUPPORTED_RUNTIMES "libc;libunwind;libcxxabi;pstl;libcxx;compiler-rt;openmp;llvm-libgcc;offload") set(LLVM_ENABLE_RUNTIMES "" CACHE STRING "Semicolon-separated list of runtimes to build, or \"all\" (${LLVM_DEFAULT_RUNTIMES}). Supported runtimes are ${LLVM_SUPPORTED_RUNTIMES}.") if(LLVM_ENABLE_RUNTIMES STREQUAL "all") diff --git a/openmp/libomptarget/CMakeLists.txt b/offload/CMakeLists.txt similarity index 56% rename from openmp/libomptarget/CMakeLists.txt rename to offload/CMakeLists.txt index 531198fae016..b23ffdcbd5aa 100644 --- a/openmp/libomptarget/CMakeLists.txt +++ b/offload/CMakeLists.txt @@ -10,12 +10,106 @@ # ##===----------------------------------------------------------------------===## -if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - message(FATAL_ERROR "Direct configuration not supported, please use parent directory!") +cmake_minimum_required(VERSION 3.20.0) + +if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") + set(OPENMP_STANDALONE_BUILD TRUE) + project(offload C CXX ASM) +endif() + +set(ENABLE_LIBOMPTARGET ON) +# Currently libomptarget cannot be compiled on Windows or MacOS X. +# Since the device plugins are only supported on Linux anyway, +# there is no point in trying to compile libomptarget on other OSes. +# 32-bit systems are not supported either. +if (APPLE OR WIN32 OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + set(ENABLE_LIBOMPTARGET OFF) endif() -# Add cmake directory to search for custom cmake functions. -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules ${CMAKE_MODULE_PATH}) +option(OPENMP_ENABLE_LIBOMPTARGET "Enable building libomptarget for offloading." + ${ENABLE_LIBOMPTARGET}) +if (OPENMP_ENABLE_LIBOMPTARGET) + # Check that the library can actually be built. + if (APPLE OR WIN32) + message(FATAL_ERROR "libomptarget cannot be built on Windows and MacOS X!") + elseif (NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + message(FATAL_ERROR "Host compiler must support C++17 to build libomptarget!") + elseif (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + message(FATAL_ERROR "libomptarget on 32-bit systems are not supported!") + endif() +endif() + +# TODO: Leftover from the move, could probably be just LLVM_LIBDIR_SUFFIX everywhere. +set(OFFLOAD_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}") + +set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + +# Add path for custom modules +list(INSERT CMAKE_MODULE_PATH 0 + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" + ) + +if (OPENMP_STANDALONE_BUILD) + # CMAKE_BUILD_TYPE was not set, default to Release. + if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) + endif() + + # Group common settings. + set(OPENMP_ENABLE_WERROR FALSE CACHE BOOL + "Enable -Werror flags to turn warnings into errors for supporting compilers.") + set(OPENMP_LIBDIR_SUFFIX "" CACHE STRING + "Suffix of lib installation directory, e.g. 64 => lib64") + # Do not use OPENMP_LIBDIR_SUFFIX directly, use OPENMP_INSTALL_LIBDIR. + set(OPENMP_INSTALL_LIBDIR "lib${OPENMP_LIBDIR_SUFFIX}") + + # Group test settings. + set(OPENMP_TEST_C_COMPILER ${CMAKE_C_COMPILER} CACHE STRING + "C compiler to use for testing OpenMP runtime libraries.") + set(OPENMP_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE STRING + "C++ compiler to use for testing OpenMP runtime libraries.") + set(OPENMP_TEST_Fortran_COMPILER ${CMAKE_Fortran_COMPILER} CACHE STRING + "FORTRAN compiler to use for testing OpenMP runtime libraries.") + set(OPENMP_LLVM_TOOLS_DIR "" CACHE PATH "Path to LLVM tools for testing.") + + set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") + set(CMAKE_CXX_STANDARD_REQUIRED NO) + set(CMAKE_CXX_EXTENSIONS NO) +else() + set(OPENMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR}) + # If building in tree, we honor the same install suffix LLVM uses. + set(OPENMP_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}") + + if (NOT MSVC) + set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang) + set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++) + else() + set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe) + set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++.exe) + endif() + + # Check for flang + if (NOT MSVC) + set(OPENMP_TEST_Fortran_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang-new) + else() + set(OPENMP_TEST_Fortran_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang-new.exe) + endif() + + # Set fortran test compiler if flang is found + if (EXISTS "${OPENMP_TEST_Fortran_COMPILER}") + message("Using local flang build at ${OPENMP_TEST_Fortran_COMPILER}") + else() + unset(OPENMP_TEST_Fortran_COMPILER) + endif() + + # If not standalone, set CMAKE_CXX_STANDARD but don't set the global cache value, + # only set it locally for OpenMP. + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED NO) + set(CMAKE_CXX_EXTENSIONS NO) +endif() # Set the path of all resulting libraries to a unified location so that it can # be used for testing. @@ -36,6 +130,9 @@ include(LibomptargetUtils) # Get dependencies for the different components of the project. include(LibomptargetGetDependencies) +# Set up testing infrastructure. +include(OpenMPTesting) + # LLVM source tree is required at build time for libomptarget if (NOT LIBOMPTARGET_LLVM_INCLUDE_DIRS) message(FATAL_ERROR "Missing definition for LIBOMPTARGET_LLVM_INCLUDE_DIRS") @@ -101,6 +198,58 @@ if (LIBOMPTARGET_USE_LTO) list(APPEND offload_link_flags ${CMAKE_CXX_COMPILE_OPTIONS_IPO}) endif() +if(OPENMP_STANDALONE_BUILD) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + execute_process( + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${CMAKE_CXX_COMPILER} --print-resource-dir + RESULT_VARIABLE COMMAND_RETURN_CODE + OUTPUT_VARIABLE COMPILER_RESOURCE_DIR + ) + endif() + + set(LIBOMP_HAVE_OMPT_SUPPORT FALSE) + set(LIBOMP_OMPT_SUPPORT FALSE) + + find_path ( + LIBOMP_OMP_TOOLS_INCLUDE_DIR + NAMES + omp-tools.h + HINTS + ${COMPILER_RESOURCE_DIR}/include + ${CMAKE_INSTALL_PREFIX}/include + ) + + if(LIBOMP_OMP_TOOLS_INCLUDE_DIR) + set(LIBOMP_HAVE_OMPT_SUPPORT TRUE) + set(LIBOMP_OMPT_SUPPORT TRUE) + endif() + + # LLVM_LIBRARY_DIRS set by find_package(LLVM) in LibomptargetGetDependencies + find_library ( + LIBOMP_STANDALONE + NAMES + omp + HINTS + ${CMAKE_INSTALL_PREFIX}/lib + ${LLVM_LIBRARY_DIRS} + REQUIRED + ) +# Check LIBOMP_HAVE_VERSION_SCRIPT_FLAG + include(LLVMCheckCompilerLinkerFlag) + if(NOT APPLE) + llvm_check_compiler_linker_flag(C "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/../openmp/runtime/src/exports_test_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG) + endif() + + macro(pythonize_bool var) + if (${var}) + set(${var} True) + else() + set(${var} False) + endif() + endmacro() +endif() + # OMPT support for libomptarget # Follow host OMPT support and check if host support has been requested. # LIBOMP_HAVE_OMPT_SUPPORT indicates whether host OMPT support has been implemented. @@ -127,13 +276,10 @@ pythonize_bool(LIBOMPTARGET_GPU_LIBC_SUPPORT) set(LIBOMPTARGET_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) message(STATUS "OpenMP tools dir in libomptarget: ${LIBOMP_OMP_TOOLS_INCLUDE_DIR}") -include_directories(${LIBOMP_OMP_TOOLS_INCLUDE_DIR}) +if(LIBOMP_OMP_TOOLS_INCLUDE_DIR) + include_directories(${LIBOMP_OMP_TOOLS_INCLUDE_DIR}) +endif() -# Definitions for testing, for reuse when testing libomptarget-nvptx. -set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${LIBOMP_INCLUDE_DIR}" CACHE STRING - "Path to folder containing omp.h") -set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${LIBOMP_LIBRARY_DIR}" CACHE STRING - "Path to folder containing libomp.so, and libLLVMSupport.so with profiling enabled") set(LIBOMPTARGET_LLVM_LIBRARY_DIR "${LLVM_LIBRARY_DIR}" CACHE STRING "Path to folder containing llvm library libomptarget.so") set(LIBOMPTARGET_LLVM_LIBRARY_INTDIR "${LIBOMPTARGET_INTDIR}" CACHE STRING diff --git a/openmp/libomptarget/DeviceRTL/CMakeLists.txt b/offload/DeviceRTL/CMakeLists.txt similarity index 99% rename from openmp/libomptarget/DeviceRTL/CMakeLists.txt rename to offload/DeviceRTL/CMakeLists.txt index 2e7f28df24d6..cbc859059100 100644 --- a/openmp/libomptarget/DeviceRTL/CMakeLists.txt +++ b/offload/DeviceRTL/CMakeLists.txt @@ -233,7 +233,7 @@ function(compileDeviceRTLLibrary target_cpu target_name target_triple) set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${bclib_name} ${LIBOMPTARGET_LIBRARY_DIR}/${bclib_name}) # Install bitcode library under the lib destination folder. - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${bclib_name} DESTINATION "${OPENMP_INSTALL_LIBDIR}") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${bclib_name} DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") set(target_feature "") if("${target_triple}" STREQUAL "nvptx64-nvidia-cuda") @@ -312,4 +312,4 @@ set_target_properties(omptarget.devicertl PROPERTIES ) target_link_libraries(omptarget.devicertl PRIVATE omptarget.devicertl.all_objs) -install(TARGETS omptarget.devicertl ARCHIVE DESTINATION ${OPENMP_INSTALL_LIBDIR}) +install(TARGETS omptarget.devicertl ARCHIVE DESTINATION ${OFFLOAD_INSTALL_LIBDIR}) diff --git a/openmp/libomptarget/DeviceRTL/include/Allocator.h b/offload/DeviceRTL/include/Allocator.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Allocator.h rename to offload/DeviceRTL/include/Allocator.h diff --git a/openmp/libomptarget/DeviceRTL/include/Configuration.h b/offload/DeviceRTL/include/Configuration.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Configuration.h rename to offload/DeviceRTL/include/Configuration.h diff --git a/openmp/libomptarget/DeviceRTL/include/Debug.h b/offload/DeviceRTL/include/Debug.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Debug.h rename to offload/DeviceRTL/include/Debug.h diff --git a/openmp/libomptarget/DeviceRTL/include/Interface.h b/offload/DeviceRTL/include/Interface.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Interface.h rename to offload/DeviceRTL/include/Interface.h diff --git a/openmp/libomptarget/DeviceRTL/include/LibC.h b/offload/DeviceRTL/include/LibC.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/LibC.h rename to offload/DeviceRTL/include/LibC.h diff --git a/openmp/libomptarget/DeviceRTL/include/Mapping.h b/offload/DeviceRTL/include/Mapping.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Mapping.h rename to offload/DeviceRTL/include/Mapping.h diff --git a/openmp/libomptarget/DeviceRTL/include/State.h b/offload/DeviceRTL/include/State.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/State.h rename to offload/DeviceRTL/include/State.h diff --git a/openmp/libomptarget/DeviceRTL/include/Synchronization.h b/offload/DeviceRTL/include/Synchronization.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Synchronization.h rename to offload/DeviceRTL/include/Synchronization.h diff --git a/openmp/libomptarget/DeviceRTL/include/Types.h b/offload/DeviceRTL/include/Types.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Types.h rename to offload/DeviceRTL/include/Types.h diff --git a/openmp/libomptarget/DeviceRTL/include/Utils.h b/offload/DeviceRTL/include/Utils.h similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/Utils.h rename to offload/DeviceRTL/include/Utils.h diff --git a/openmp/libomptarget/DeviceRTL/include/generated_microtask_cases.gen b/offload/DeviceRTL/include/generated_microtask_cases.gen similarity index 100% rename from openmp/libomptarget/DeviceRTL/include/generated_microtask_cases.gen rename to offload/DeviceRTL/include/generated_microtask_cases.gen diff --git a/openmp/libomptarget/DeviceRTL/src/Allocator.cpp b/offload/DeviceRTL/src/Allocator.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Allocator.cpp rename to offload/DeviceRTL/src/Allocator.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Configuration.cpp b/offload/DeviceRTL/src/Configuration.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Configuration.cpp rename to offload/DeviceRTL/src/Configuration.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Debug.cpp b/offload/DeviceRTL/src/Debug.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Debug.cpp rename to offload/DeviceRTL/src/Debug.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Kernel.cpp b/offload/DeviceRTL/src/Kernel.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Kernel.cpp rename to offload/DeviceRTL/src/Kernel.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/LibC.cpp b/offload/DeviceRTL/src/LibC.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/LibC.cpp rename to offload/DeviceRTL/src/LibC.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp b/offload/DeviceRTL/src/Mapping.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Mapping.cpp rename to offload/DeviceRTL/src/Mapping.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Misc.cpp b/offload/DeviceRTL/src/Misc.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Misc.cpp rename to offload/DeviceRTL/src/Misc.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Parallelism.cpp b/offload/DeviceRTL/src/Parallelism.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Parallelism.cpp rename to offload/DeviceRTL/src/Parallelism.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Reduction.cpp b/offload/DeviceRTL/src/Reduction.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Reduction.cpp rename to offload/DeviceRTL/src/Reduction.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/State.cpp b/offload/DeviceRTL/src/State.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/State.cpp rename to offload/DeviceRTL/src/State.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Stub.cpp b/offload/DeviceRTL/src/Stub.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Stub.cpp rename to offload/DeviceRTL/src/Stub.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Synchronization.cpp b/offload/DeviceRTL/src/Synchronization.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Synchronization.cpp rename to offload/DeviceRTL/src/Synchronization.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Tasking.cpp b/offload/DeviceRTL/src/Tasking.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Tasking.cpp rename to offload/DeviceRTL/src/Tasking.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Utils.cpp b/offload/DeviceRTL/src/Utils.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Utils.cpp rename to offload/DeviceRTL/src/Utils.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/Workshare.cpp b/offload/DeviceRTL/src/Workshare.cpp similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/Workshare.cpp rename to offload/DeviceRTL/src/Workshare.cpp diff --git a/openmp/libomptarget/DeviceRTL/src/exports b/offload/DeviceRTL/src/exports similarity index 100% rename from openmp/libomptarget/DeviceRTL/src/exports rename to offload/DeviceRTL/src/exports diff --git a/openmp/libomptarget/README.txt b/offload/README.txt similarity index 100% rename from openmp/libomptarget/README.txt rename to offload/README.txt diff --git a/openmp/libomptarget/cmake/Modules/LibomptargetGetDependencies.cmake b/offload/cmake/Modules/LibomptargetGetDependencies.cmake similarity index 100% rename from openmp/libomptarget/cmake/Modules/LibomptargetGetDependencies.cmake rename to offload/cmake/Modules/LibomptargetGetDependencies.cmake diff --git a/openmp/libomptarget/cmake/Modules/LibomptargetUtils.cmake b/offload/cmake/Modules/LibomptargetUtils.cmake similarity index 100% rename from openmp/libomptarget/cmake/Modules/LibomptargetUtils.cmake rename to offload/cmake/Modules/LibomptargetUtils.cmake diff --git a/offload/cmake/OpenMPTesting.cmake b/offload/cmake/OpenMPTesting.cmake new file mode 100644 index 000000000000..11eafeb76426 --- /dev/null +++ b/offload/cmake/OpenMPTesting.cmake @@ -0,0 +1,238 @@ +# Keep track if we have all dependencies. +set(ENABLE_CHECK_TARGETS TRUE) + +# Function to find required dependencies for testing. +function(find_standalone_test_dependencies) + find_package (Python3 COMPONENTS Interpreter) + + if (NOT Python3_Interpreter_FOUND) + message(STATUS "Could not find Python.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE) + return() + else() + set(Python3_EXECUTABLE ${Python3_EXECUTABLE} PARENT_SCOPE) + endif() + + # Find executables. + find_program(OPENMP_LLVM_LIT_EXECUTABLE + NAMES llvm-lit.py llvm-lit lit.py lit + PATHS ${OPENMP_LLVM_TOOLS_DIR}) + if (NOT OPENMP_LLVM_LIT_EXECUTABLE) + message(STATUS "Cannot find llvm-lit.") + message(STATUS "Please put llvm-lit in your PATH, set OPENMP_LLVM_LIT_EXECUTABLE to its full path, or point OPENMP_LLVM_TOOLS_DIR to its directory.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE) + return() + endif() + + find_program(OPENMP_FILECHECK_EXECUTABLE + NAMES FileCheck + PATHS ${OPENMP_LLVM_TOOLS_DIR}) + if (NOT OPENMP_FILECHECK_EXECUTABLE) + message(STATUS "Cannot find FileCheck.") + message(STATUS "Please put FileCheck in your PATH, set OPENMP_FILECHECK_EXECUTABLE to its full path, or point OPENMP_LLVM_TOOLS_DIR to its directory.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE) + return() + endif() + + find_program(OPENMP_NOT_EXECUTABLE + NAMES not + PATHS ${OPENMP_LLVM_TOOLS_DIR}) + if (NOT OPENMP_NOT_EXECUTABLE) + message(STATUS "Cannot find 'not'.") + message(STATUS "Please put 'not' in your PATH, set OPENMP_NOT_EXECUTABLE to its full path, or point OPENMP_LLVM_TOOLS_DIR to its directory.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE) + return() + endif() +endfunction() + +if (${OPENMP_STANDALONE_BUILD}) + find_standalone_test_dependencies() + + # Set lit arguments. + set(DEFAULT_LIT_ARGS "-sv --show-unsupported --show-xfail") + if (MSVC OR XCODE) + set(DEFAULT_LIT_ARGS "${DEFAULT_LIT_ARGS} --no-progress-bar") + endif() + if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") + set(DEFAULT_LIT_ARGS "${DEFAULT_LIT_ARGS} --time-tests --timeout=1800") + endif() + set(OPENMP_LIT_ARGS "${DEFAULT_LIT_ARGS}" CACHE STRING "Options for lit.") + separate_arguments(OPENMP_LIT_ARGS) +else() + if (NOT TARGET "FileCheck") + message(STATUS "Cannot find 'FileCheck'.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE) + else() + set(OPENMP_FILECHECK_EXECUTABLE ${LLVM_RUNTIME_OUTPUT_INTDIR}/FileCheck) + endif() + set(OPENMP_NOT_EXECUTABLE ${LLVM_RUNTIME_OUTPUT_INTDIR}/not) +endif() + +# Macro to extract information about compiler from file. (no own scope) +macro(extract_test_compiler_information lang file) + file(READ ${file} information) + list(GET information 0 path) + list(GET information 1 id) + list(GET information 2 version) + list(GET information 3 openmp_flags) + list(GET information 4 has_tsan_flags) + list(GET information 5 has_omit_frame_pointer_flags) + list(GET information 6 has_omp_h) + + set(OPENMP_TEST_${lang}_COMPILER_PATH ${path}) + set(OPENMP_TEST_${lang}_COMPILER_ID ${id}) + set(OPENMP_TEST_${lang}_COMPILER_VERSION ${version}) + set(OPENMP_TEST_${lang}_COMPILER_OPENMP_FLAGS ${openmp_flags}) + set(OPENMP_TEST_${lang}_COMPILER_HAS_TSAN_FLAGS ${has_tsan_flags}) + set(OPENMP_TEST_${lang}_COMPILER_HAS_OMIT_FRAME_POINTER_FLAGS ${has_omit_frame_pointer_flags}) + set(OPENMP_TEST_${lang}_COMPILER_HAS_OMP_H ${has_omp_h}) +endmacro() + +# Function to set variables with information about the test compiler. +function(set_test_compiler_information dir) + extract_test_compiler_information(C ${dir}/CCompilerInformation.txt) + extract_test_compiler_information(CXX ${dir}/CXXCompilerInformation.txt) + if (NOT("${OPENMP_TEST_C_COMPILER_ID}" STREQUAL "${OPENMP_TEST_CXX_COMPILER_ID}" AND + "${OPENMP_TEST_C_COMPILER_VERSION}" STREQUAL "${OPENMP_TEST_CXX_COMPILER_VERSION}")) + message(STATUS "Test compilers for C and C++ don't match.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE PARENT_SCOPE) + else() + set(OPENMP_TEST_COMPILER_ID "${OPENMP_TEST_C_COMPILER_ID}" PARENT_SCOPE) + set(OPENMP_TEST_COMPILER_VERSION "${OPENMP_TEST_C_COMPILER_VERSION}" PARENT_SCOPE) + set(OPENMP_TEST_COMPILER_OPENMP_FLAGS "${OPENMP_TEST_C_COMPILER_OPENMP_FLAGS}" PARENT_SCOPE) + set(OPENMP_TEST_COMPILER_HAS_TSAN_FLAGS "${OPENMP_TEST_C_COMPILER_HAS_TSAN_FLAGS}" PARENT_SCOPE) + set(OPENMP_TEST_COMPILER_HAS_OMIT_FRAME_POINTER_FLAGS "${OPENMP_TEST_C_COMPILER_HAS_OMIT_FRAME_POINTER_FLAGS}" PARENT_SCOPE) + set(OPENMP_TEST_COMPILER_HAS_OMP_H "${OPENMP_TEST_C_COMPILER_HAS_OMP_H}" PARENT_SCOPE) + + # Determine major version. + string(REGEX MATCH "[0-9]+" major "${OPENMP_TEST_C_COMPILER_VERSION}") + string(REGEX MATCH "[0-9]+\\.[0-9]+" majorminor "${OPENMP_TEST_C_COMPILER_VERSION}") + set(OPENMP_TEST_COMPILER_VERSION_MAJOR "${major}" PARENT_SCOPE) + set(OPENMP_TEST_COMPILER_VERSION_MAJOR_MINOR "${majorminor}" PARENT_SCOPE) + endif() +endfunction() + +if (${OPENMP_STANDALONE_BUILD}) + # Detect compiler that should be used for testing. + # We cannot use ExternalProject_Add() because its configuration runs when this + # project is built which is too late for detecting the compiler... + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler) + execute_process( + COMMAND ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/DetectTestCompiler + -DCMAKE_C_COMPILER=${OPENMP_TEST_C_COMPILER} + -DCMAKE_CXX_COMPILER=${OPENMP_TEST_CXX_COMPILER} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler + OUTPUT_VARIABLE DETECT_COMPILER_OUT + ERROR_VARIABLE DETECT_COMPILER_ERR + RESULT_VARIABLE DETECT_COMPILER_RESULT) + if (DETECT_COMPILER_RESULT) + message(STATUS "Could not detect test compilers.") + message(WARNING "The check targets will not be available!") + set(ENABLE_CHECK_TARGETS FALSE) + else() + set_test_compiler_information(${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler) + endif() +else() + # Set the information that we know. + set(OPENMP_TEST_COMPILER_ID "Clang") + # Cannot use CLANG_VERSION because we are not guaranteed that this is already set. + set(OPENMP_TEST_COMPILER_VERSION "${LLVM_VERSION}") + set(OPENMP_TEST_COMPILER_VERSION_MAJOR "${LLVM_VERSION_MAJOR}") + set(OPENMP_TEST_COMPILER_VERSION_MAJOR_MINOR "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}") + # Unfortunately the top-level cmake/config-ix.cmake file mangles CMake's + # CMAKE_THREAD_LIBS_INIT variable from the FindThreads package, so work + # around that, until it is fixed there. + if("${CMAKE_THREAD_LIBS_INIT}" STREQUAL "-lpthread") + set(OPENMP_TEST_COMPILER_THREAD_FLAGS "-pthread") + else() + set(OPENMP_TEST_COMPILER_THREAD_FLAGS "${CMAKE_THREAD_LIBS_INIT}") + endif() + if(TARGET tsan) + set(OPENMP_TEST_COMPILER_HAS_TSAN_FLAGS 1) + else() + set(OPENMP_TEST_COMPILER_HAS_TSAN_FLAGS 0) + endif() + set(OPENMP_TEST_COMPILER_HAS_OMP_H 1) + set(OPENMP_TEST_COMPILER_OPENMP_FLAGS "-fopenmp ${OPENMP_TEST_COMPILER_THREAD_FLAGS}") + set(OPENMP_TEST_COMPILER_HAS_OMIT_FRAME_POINTER_FLAGS 1) +endif() + +# Function to set compiler features for use in lit. +function(update_test_compiler_features) + set(FEATURES "[") + set(first TRUE) + foreach(feat IN LISTS OPENMP_TEST_COMPILER_FEATURE_LIST) + if (NOT first) + string(APPEND FEATURES ", ") + endif() + set(first FALSE) + string(APPEND FEATURES "'${feat}'") + endforeach() + string(APPEND FEATURES "]") + set(OPENMP_TEST_COMPILER_FEATURES ${FEATURES} PARENT_SCOPE) +endfunction() + +function(set_test_compiler_features) + if ("${OPENMP_TEST_COMPILER_ID}" STREQUAL "GNU") + set(comp "gcc") + elseif ("${OPENMP_TEST_COMPILER_ID}" STREQUAL "Intel") + set(comp "icc") + else() + # Just use the lowercase of the compiler ID as fallback. + string(TOLOWER "${OPENMP_TEST_COMPILER_ID}" comp) + endif() + set(OPENMP_TEST_COMPILER_FEATURE_LIST ${comp} ${comp}-${OPENMP_TEST_COMPILER_VERSION_MAJOR} ${comp}-${OPENMP_TEST_COMPILER_VERSION_MAJOR_MINOR} ${comp}-${OPENMP_TEST_COMPILER_VERSION} PARENT_SCOPE) +endfunction() +set_test_compiler_features() +update_test_compiler_features() + +# Function to add a testsuite for an OpenMP runtime library. +function(add_offload_testsuite target comment) + if (NOT ENABLE_CHECK_TARGETS) + add_custom_target(${target} + COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, dependencies not found.") + message(STATUS "${target} does nothing.") + return() + endif() + + cmake_parse_arguments(ARG "EXCLUDE_FROM_CHECK_ALL" "" "DEPENDS;ARGS" ${ARGN}) + # EXCLUDE_FROM_CHECK_ALL excludes the test ${target} out of check-offload. + if (NOT ARG_EXCLUDE_FROM_CHECK_ALL) + # Register the testsuites and depends for the check-offload rule. + set_property(GLOBAL APPEND PROPERTY OPENMP_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS}) + set_property(GLOBAL APPEND PROPERTY OPENMP_LIT_DEPENDS ${ARG_DEPENDS}) + endif() + + if (${OPENMP_STANDALONE_BUILD}) + set(LIT_ARGS ${OPENMP_LIT_ARGS} ${ARG_ARGS}) + add_custom_target(${target} + COMMAND ${Python3_EXECUTABLE} ${OPENMP_LLVM_LIT_EXECUTABLE} ${LIT_ARGS} ${ARG_UNPARSED_ARGUMENTS} + COMMENT ${comment} + DEPENDS ${ARG_DEPENDS} + USES_TERMINAL + ) + else() + if (ARG_EXCLUDE_FROM_CHECK_ALL) + add_lit_testsuite(${target} + ${comment} + ${ARG_UNPARSED_ARGUMENTS} + EXCLUDE_FROM_CHECK_ALL + DEPENDS clang FileCheck not ${ARG_DEPENDS} + ARGS ${ARG_ARGS} + ) + else() + add_lit_testsuite(${target} + ${comment} + ${ARG_UNPARSED_ARGUMENTS} + DEPENDS clang FileCheck not ${ARG_DEPENDS} + ARGS ${ARG_ARGS} + ) + endif() + endif() +endfunction() diff --git a/openmp/libomptarget/docs/declare_target_indirect.md b/offload/docs/declare_target_indirect.md similarity index 100% rename from openmp/libomptarget/docs/declare_target_indirect.md rename to offload/docs/declare_target_indirect.md diff --git a/openmp/libomptarget/include/DeviceImage.h b/offload/include/DeviceImage.h similarity index 100% rename from openmp/libomptarget/include/DeviceImage.h rename to offload/include/DeviceImage.h diff --git a/openmp/libomptarget/include/ExclusiveAccess.h b/offload/include/ExclusiveAccess.h similarity index 100% rename from openmp/libomptarget/include/ExclusiveAccess.h rename to offload/include/ExclusiveAccess.h diff --git a/openmp/libomptarget/include/OffloadEntry.h b/offload/include/OffloadEntry.h similarity index 100% rename from openmp/libomptarget/include/OffloadEntry.h rename to offload/include/OffloadEntry.h diff --git a/openmp/libomptarget/include/OffloadPolicy.h b/offload/include/OffloadPolicy.h similarity index 100% rename from openmp/libomptarget/include/OffloadPolicy.h rename to offload/include/OffloadPolicy.h diff --git a/openmp/libomptarget/include/OpenMP/InternalTypes.h b/offload/include/OpenMP/InternalTypes.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/InternalTypes.h rename to offload/include/OpenMP/InternalTypes.h diff --git a/openmp/libomptarget/include/OpenMP/InteropAPI.h b/offload/include/OpenMP/InteropAPI.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/InteropAPI.h rename to offload/include/OpenMP/InteropAPI.h diff --git a/openmp/libomptarget/include/OpenMP/Mapping.h b/offload/include/OpenMP/Mapping.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/Mapping.h rename to offload/include/OpenMP/Mapping.h diff --git a/openmp/libomptarget/include/OpenMP/OMPT/Callback.h b/offload/include/OpenMP/OMPT/Callback.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/OMPT/Callback.h rename to offload/include/OpenMP/OMPT/Callback.h diff --git a/openmp/libomptarget/include/OpenMP/OMPT/Connector.h b/offload/include/OpenMP/OMPT/Connector.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/OMPT/Connector.h rename to offload/include/OpenMP/OMPT/Connector.h diff --git a/openmp/libomptarget/include/OpenMP/OMPT/Interface.h b/offload/include/OpenMP/OMPT/Interface.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/OMPT/Interface.h rename to offload/include/OpenMP/OMPT/Interface.h diff --git a/openmp/libomptarget/include/OpenMP/omp.h b/offload/include/OpenMP/omp.h similarity index 100% rename from openmp/libomptarget/include/OpenMP/omp.h rename to offload/include/OpenMP/omp.h diff --git a/openmp/libomptarget/include/PluginManager.h b/offload/include/PluginManager.h similarity index 100% rename from openmp/libomptarget/include/PluginManager.h rename to offload/include/PluginManager.h diff --git a/openmp/libomptarget/include/Shared/APITypes.h b/offload/include/Shared/APITypes.h similarity index 100% rename from openmp/libomptarget/include/Shared/APITypes.h rename to offload/include/Shared/APITypes.h diff --git a/openmp/libomptarget/include/Shared/Debug.h b/offload/include/Shared/Debug.h similarity index 100% rename from openmp/libomptarget/include/Shared/Debug.h rename to offload/include/Shared/Debug.h diff --git a/openmp/libomptarget/include/Shared/Environment.h b/offload/include/Shared/Environment.h similarity index 100% rename from openmp/libomptarget/include/Shared/Environment.h rename to offload/include/Shared/Environment.h diff --git a/openmp/libomptarget/include/Shared/EnvironmentVar.h b/offload/include/Shared/EnvironmentVar.h similarity index 100% rename from openmp/libomptarget/include/Shared/EnvironmentVar.h rename to offload/include/Shared/EnvironmentVar.h diff --git a/openmp/libomptarget/include/Shared/PluginAPI.h b/offload/include/Shared/PluginAPI.h similarity index 100% rename from openmp/libomptarget/include/Shared/PluginAPI.h rename to offload/include/Shared/PluginAPI.h diff --git a/openmp/libomptarget/include/Shared/PluginAPI.inc b/offload/include/Shared/PluginAPI.inc similarity index 100% rename from openmp/libomptarget/include/Shared/PluginAPI.inc rename to offload/include/Shared/PluginAPI.inc diff --git a/openmp/libomptarget/include/Shared/Profile.h b/offload/include/Shared/Profile.h similarity index 100% rename from openmp/libomptarget/include/Shared/Profile.h rename to offload/include/Shared/Profile.h diff --git a/openmp/libomptarget/include/Shared/Requirements.h b/offload/include/Shared/Requirements.h similarity index 100% rename from openmp/libomptarget/include/Shared/Requirements.h rename to offload/include/Shared/Requirements.h diff --git a/openmp/libomptarget/include/Shared/SourceInfo.h b/offload/include/Shared/SourceInfo.h similarity index 100% rename from openmp/libomptarget/include/Shared/SourceInfo.h rename to offload/include/Shared/SourceInfo.h diff --git a/openmp/libomptarget/include/Shared/Utils.h b/offload/include/Shared/Utils.h similarity index 100% rename from openmp/libomptarget/include/Shared/Utils.h rename to offload/include/Shared/Utils.h diff --git a/openmp/libomptarget/include/Utils/ExponentialBackoff.h b/offload/include/Utils/ExponentialBackoff.h similarity index 100% rename from openmp/libomptarget/include/Utils/ExponentialBackoff.h rename to offload/include/Utils/ExponentialBackoff.h diff --git a/openmp/libomptarget/include/device.h b/offload/include/device.h similarity index 100% rename from openmp/libomptarget/include/device.h rename to offload/include/device.h diff --git a/openmp/libomptarget/include/omptarget.h b/offload/include/omptarget.h similarity index 100% rename from openmp/libomptarget/include/omptarget.h rename to offload/include/omptarget.h diff --git a/openmp/libomptarget/include/rtl.h b/offload/include/rtl.h similarity index 100% rename from openmp/libomptarget/include/rtl.h rename to offload/include/rtl.h diff --git a/openmp/libomptarget/plugins-nextgen/CMakeLists.txt b/offload/plugins-nextgen/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/plugins-nextgen/CMakeLists.txt rename to offload/plugins-nextgen/CMakeLists.txt diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt b/offload/plugins-nextgen/amdgpu/CMakeLists.txt similarity index 97% rename from openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt rename to offload/plugins-nextgen/amdgpu/CMakeLists.txt index 40df77102c78..f5f7096137c2 100644 --- a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/offload/plugins-nextgen/amdgpu/CMakeLists.txt @@ -59,6 +59,6 @@ else() endif() # Install plugin under the lib destination folder. -install(TARGETS omptarget.rtl.amdgpu LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") +install(TARGETS omptarget.rtl.amdgpu LIBRARY DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") set_target_properties(omptarget.rtl.amdgpu PROPERTIES INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp rename to offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h rename to offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/dynamic_hsa/hsa_ext_amd.h b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa_ext_amd.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/amdgpu/dynamic_hsa/hsa_ext_amd.h rename to offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa_ext_amd.h diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp b/offload/plugins-nextgen/amdgpu/src/rtl.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp rename to offload/plugins-nextgen/amdgpu/src/rtl.cpp diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h b/offload/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h rename to offload/plugins-nextgen/amdgpu/utils/UtilitiesRTL.h diff --git a/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt b/offload/plugins-nextgen/common/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt rename to offload/plugins-nextgen/common/CMakeLists.txt diff --git a/openmp/libomptarget/plugins-nextgen/common/OMPT/OmptCallback.cpp b/offload/plugins-nextgen/common/OMPT/OmptCallback.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/OMPT/OmptCallback.cpp rename to offload/plugins-nextgen/common/OMPT/OmptCallback.cpp diff --git a/openmp/libomptarget/plugins-nextgen/common/include/DLWrap.h b/offload/plugins-nextgen/common/include/DLWrap.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/DLWrap.h rename to offload/plugins-nextgen/common/include/DLWrap.h diff --git a/openmp/libomptarget/plugins-nextgen/common/include/GlobalHandler.h b/offload/plugins-nextgen/common/include/GlobalHandler.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/GlobalHandler.h rename to offload/plugins-nextgen/common/include/GlobalHandler.h diff --git a/openmp/libomptarget/plugins-nextgen/common/include/JIT.h b/offload/plugins-nextgen/common/include/JIT.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/JIT.h rename to offload/plugins-nextgen/common/include/JIT.h diff --git a/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h b/offload/plugins-nextgen/common/include/MemoryManager.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h rename to offload/plugins-nextgen/common/include/MemoryManager.h diff --git a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h rename to offload/plugins-nextgen/common/include/PluginInterface.h diff --git a/openmp/libomptarget/plugins-nextgen/common/include/RPC.h b/offload/plugins-nextgen/common/include/RPC.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/RPC.h rename to offload/plugins-nextgen/common/include/RPC.h diff --git a/openmp/libomptarget/plugins-nextgen/common/include/Utils/ELF.h b/offload/plugins-nextgen/common/include/Utils/ELF.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/include/Utils/ELF.h rename to offload/plugins-nextgen/common/include/Utils/ELF.h diff --git a/openmp/libomptarget/plugins-nextgen/common/src/GlobalHandler.cpp b/offload/plugins-nextgen/common/src/GlobalHandler.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/src/GlobalHandler.cpp rename to offload/plugins-nextgen/common/src/GlobalHandler.cpp diff --git a/openmp/libomptarget/plugins-nextgen/common/src/JIT.cpp b/offload/plugins-nextgen/common/src/JIT.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/src/JIT.cpp rename to offload/plugins-nextgen/common/src/JIT.cpp diff --git a/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp rename to offload/plugins-nextgen/common/src/PluginInterface.cpp diff --git a/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp b/offload/plugins-nextgen/common/src/RPC.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp rename to offload/plugins-nextgen/common/src/RPC.cpp diff --git a/openmp/libomptarget/plugins-nextgen/common/src/Utils/ELF.cpp b/offload/plugins-nextgen/common/src/Utils/ELF.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/common/src/Utils/ELF.cpp rename to offload/plugins-nextgen/common/src/Utils/ELF.cpp diff --git a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt b/offload/plugins-nextgen/cuda/CMakeLists.txt similarity index 96% rename from openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt rename to offload/plugins-nextgen/cuda/CMakeLists.txt index b3530462aa19..0284bd22d2a4 100644 --- a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt +++ b/offload/plugins-nextgen/cuda/CMakeLists.txt @@ -53,6 +53,6 @@ else() endif() # Install plugin under the lib destination folder. -install(TARGETS omptarget.rtl.cuda LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") +install(TARGETS omptarget.rtl.cuda LIBRARY DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") set_target_properties(omptarget.rtl.cuda PROPERTIES INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") diff --git a/openmp/libomptarget/plugins-nextgen/cuda/dynamic_cuda/cuda.cpp b/offload/plugins-nextgen/cuda/dynamic_cuda/cuda.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/cuda/dynamic_cuda/cuda.cpp rename to offload/plugins-nextgen/cuda/dynamic_cuda/cuda.cpp diff --git a/openmp/libomptarget/plugins-nextgen/cuda/dynamic_cuda/cuda.h b/offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/cuda/dynamic_cuda/cuda.h rename to offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h diff --git a/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp b/offload/plugins-nextgen/cuda/src/rtl.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp rename to offload/plugins-nextgen/cuda/src/rtl.cpp diff --git a/openmp/libomptarget/plugins-nextgen/exports b/offload/plugins-nextgen/exports similarity index 100% rename from openmp/libomptarget/plugins-nextgen/exports rename to offload/plugins-nextgen/exports diff --git a/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt b/offload/plugins-nextgen/host/CMakeLists.txt similarity index 98% rename from openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt rename to offload/plugins-nextgen/host/CMakeLists.txt index c1493d293d30..7da18ee278d4 100644 --- a/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt +++ b/offload/plugins-nextgen/host/CMakeLists.txt @@ -33,7 +33,7 @@ endif() # Install plugin under the lib destination folder. install(TARGETS omptarget.rtl.${machine} - LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") + LIBRARY DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") set_target_properties(omptarget.rtl.${machine} PROPERTIES INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/.." POSITION_INDEPENDENT_CODE ON diff --git a/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp b/offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp rename to offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp diff --git a/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.h b/offload/plugins-nextgen/host/dynamic_ffi/ffi.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.h rename to offload/plugins-nextgen/host/dynamic_ffi/ffi.h diff --git a/openmp/libomptarget/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp similarity index 100% rename from openmp/libomptarget/plugins-nextgen/host/src/rtl.cpp rename to offload/plugins-nextgen/host/src/rtl.cpp diff --git a/openmp/libomptarget/src/CMakeLists.txt b/offload/src/CMakeLists.txt similarity index 95% rename from openmp/libomptarget/src/CMakeLists.txt rename to offload/src/CMakeLists.txt index d0971bd4ef07..fb1ad3d7ae70 100644 --- a/openmp/libomptarget/src/CMakeLists.txt +++ b/offload/src/CMakeLists.txt @@ -12,6 +12,12 @@ libomptarget_say("Building offloading runtime library libomptarget.") +if(LIBOMP_STANDALONE) + set(LIBOMP ${LIBOMP_STANDALONE}) +else() + set(LIBOMP omp) +endif() + add_llvm_library(omptarget SHARED @@ -38,7 +44,7 @@ add_llvm_library(omptarget LINK_LIBS PUBLIC - omp + ${LIBOMP} NO_INSTALL_RPATH BUILDTREE_ONLY @@ -87,4 +93,4 @@ set_target_properties(omptarget PROPERTIES POSITION_INDEPENDENT_CODE ON INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") -install(TARGETS omptarget LIBRARY COMPONENT omptarget DESTINATION "${OPENMP_INSTALL_LIBDIR}") +install(TARGETS omptarget LIBRARY COMPONENT omptarget DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") diff --git a/openmp/libomptarget/src/DeviceImage.cpp b/offload/src/DeviceImage.cpp similarity index 100% rename from openmp/libomptarget/src/DeviceImage.cpp rename to offload/src/DeviceImage.cpp diff --git a/openmp/libomptarget/src/LegacyAPI.cpp b/offload/src/LegacyAPI.cpp similarity index 100% rename from openmp/libomptarget/src/LegacyAPI.cpp rename to offload/src/LegacyAPI.cpp diff --git a/openmp/libomptarget/src/OffloadRTL.cpp b/offload/src/OffloadRTL.cpp similarity index 100% rename from openmp/libomptarget/src/OffloadRTL.cpp rename to offload/src/OffloadRTL.cpp diff --git a/openmp/libomptarget/src/OpenMP/API.cpp b/offload/src/OpenMP/API.cpp similarity index 100% rename from openmp/libomptarget/src/OpenMP/API.cpp rename to offload/src/OpenMP/API.cpp diff --git a/openmp/libomptarget/src/OpenMP/InteropAPI.cpp b/offload/src/OpenMP/InteropAPI.cpp similarity index 100% rename from openmp/libomptarget/src/OpenMP/InteropAPI.cpp rename to offload/src/OpenMP/InteropAPI.cpp diff --git a/openmp/libomptarget/src/OpenMP/Mapping.cpp b/offload/src/OpenMP/Mapping.cpp similarity index 100% rename from openmp/libomptarget/src/OpenMP/Mapping.cpp rename to offload/src/OpenMP/Mapping.cpp diff --git a/openmp/libomptarget/src/OpenMP/OMPT/Callback.cpp b/offload/src/OpenMP/OMPT/Callback.cpp similarity index 100% rename from openmp/libomptarget/src/OpenMP/OMPT/Callback.cpp rename to offload/src/OpenMP/OMPT/Callback.cpp diff --git a/openmp/libomptarget/src/PluginManager.cpp b/offload/src/PluginManager.cpp similarity index 100% rename from openmp/libomptarget/src/PluginManager.cpp rename to offload/src/PluginManager.cpp diff --git a/openmp/libomptarget/src/device.cpp b/offload/src/device.cpp similarity index 100% rename from openmp/libomptarget/src/device.cpp rename to offload/src/device.cpp diff --git a/openmp/libomptarget/src/exports b/offload/src/exports similarity index 100% rename from openmp/libomptarget/src/exports rename to offload/src/exports diff --git a/openmp/libomptarget/src/interface.cpp b/offload/src/interface.cpp similarity index 100% rename from openmp/libomptarget/src/interface.cpp rename to offload/src/interface.cpp diff --git a/openmp/libomptarget/src/omptarget.cpp b/offload/src/omptarget.cpp similarity index 100% rename from openmp/libomptarget/src/omptarget.cpp rename to offload/src/omptarget.cpp diff --git a/openmp/libomptarget/src/private.h b/offload/src/private.h similarity index 100% rename from openmp/libomptarget/src/private.h rename to offload/src/private.h diff --git a/openmp/libomptarget/test/CMakeLists.txt b/offload/test/CMakeLists.txt similarity index 78% rename from openmp/libomptarget/test/CMakeLists.txt rename to offload/test/CMakeLists.txt index a0ba233eaa57..59c9dd98f712 100644 --- a/openmp/libomptarget/test/CMakeLists.txt +++ b/offload/test/CMakeLists.txt @@ -1,6 +1,6 @@ # CMakeLists.txt file for unit testing OpenMP offloading runtime library. -if(NOT OPENMP_TEST_COMPILER_ID STREQUAL "Clang" OR - OPENMP_TEST_COMPILER_VERSION VERSION_LESS 6.0.0) +if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR + CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0.0) libomptarget_say("Can only test with Clang compiler in version 6.0.0 or later.") libomptarget_warning_say("The check-libomptarget target will not be available!") return() @@ -20,7 +20,7 @@ string(REGEX MATCHALL "([^\ ]+\ |[^\ ]+$)" SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM foreach(CURRENT_TARGET IN LISTS SYSTEM_TARGETS) string(STRIP "${CURRENT_TARGET}" CURRENT_TARGET) - add_openmp_testsuite(check-libomptarget-${CURRENT_TARGET} + add_offload_testsuite(check-libomptarget-${CURRENT_TARGET} "Running libomptarget tests" ${CMAKE_CURRENT_BINARY_DIR}/${CURRENT_TARGET} DEPENDS omptarget omp ${LIBOMPTARGET_TESTED_PLUGINS} @@ -34,7 +34,14 @@ foreach(CURRENT_TARGET IN LISTS SYSTEM_TARGETS) endforeach() -add_openmp_testsuite(check-libomptarget +add_offload_testsuite(check-libomptarget + "Running libomptarget tests" + ${LIBOMPTARGET_LIT_TESTSUITES} + EXCLUDE_FROM_CHECK_ALL + DEPENDS omptarget omp ${LIBOMPTARGET_TESTED_PLUGINS} + ARGS ${LIBOMPTARGET_LIT_ARG_LIST}) + +add_offload_testsuite(check-offload "Running libomptarget tests" ${LIBOMPTARGET_LIT_TESTSUITES} EXCLUDE_FROM_CHECK_ALL diff --git a/openmp/libomptarget/test/Inputs/basic_array.f90 b/offload/test/Inputs/basic_array.f90 similarity index 100% rename from openmp/libomptarget/test/Inputs/basic_array.f90 rename to offload/test/Inputs/basic_array.f90 diff --git a/openmp/libomptarget/test/Inputs/declare_indirect_func.c b/offload/test/Inputs/declare_indirect_func.c similarity index 100% rename from openmp/libomptarget/test/Inputs/declare_indirect_func.c rename to offload/test/Inputs/declare_indirect_func.c diff --git a/openmp/libomptarget/test/api/assert.c b/offload/test/api/assert.c similarity index 100% rename from openmp/libomptarget/test/api/assert.c rename to offload/test/api/assert.c diff --git a/openmp/libomptarget/test/api/is_initial_device.c b/offload/test/api/is_initial_device.c similarity index 100% rename from openmp/libomptarget/test/api/is_initial_device.c rename to offload/test/api/is_initial_device.c diff --git a/openmp/libomptarget/test/api/omp_device_managed_memory.c b/offload/test/api/omp_device_managed_memory.c similarity index 100% rename from openmp/libomptarget/test/api/omp_device_managed_memory.c rename to offload/test/api/omp_device_managed_memory.c diff --git a/openmp/libomptarget/test/api/omp_device_managed_memory_alloc.c b/offload/test/api/omp_device_managed_memory_alloc.c similarity index 100% rename from openmp/libomptarget/test/api/omp_device_managed_memory_alloc.c rename to offload/test/api/omp_device_managed_memory_alloc.c diff --git a/openmp/libomptarget/test/api/omp_device_memory.c b/offload/test/api/omp_device_memory.c similarity index 100% rename from openmp/libomptarget/test/api/omp_device_memory.c rename to offload/test/api/omp_device_memory.c diff --git a/openmp/libomptarget/test/api/omp_dynamic_shared_memory.c b/offload/test/api/omp_dynamic_shared_memory.c similarity index 100% rename from openmp/libomptarget/test/api/omp_dynamic_shared_memory.c rename to offload/test/api/omp_dynamic_shared_memory.c diff --git a/openmp/libomptarget/test/api/omp_dynamic_shared_memory_amdgpu.c b/offload/test/api/omp_dynamic_shared_memory_amdgpu.c similarity index 100% rename from openmp/libomptarget/test/api/omp_dynamic_shared_memory_amdgpu.c rename to offload/test/api/omp_dynamic_shared_memory_amdgpu.c diff --git a/openmp/libomptarget/test/api/omp_dynamic_shared_memory_mixed.inc b/offload/test/api/omp_dynamic_shared_memory_mixed.inc similarity index 100% rename from openmp/libomptarget/test/api/omp_dynamic_shared_memory_mixed.inc rename to offload/test/api/omp_dynamic_shared_memory_mixed.inc diff --git a/openmp/libomptarget/test/api/omp_dynamic_shared_memory_mixed_amdgpu.c b/offload/test/api/omp_dynamic_shared_memory_mixed_amdgpu.c similarity index 100% rename from openmp/libomptarget/test/api/omp_dynamic_shared_memory_mixed_amdgpu.c rename to offload/test/api/omp_dynamic_shared_memory_mixed_amdgpu.c diff --git a/openmp/libomptarget/test/api/omp_dynamic_shared_memory_mixed_nvptx.c b/offload/test/api/omp_dynamic_shared_memory_mixed_nvptx.c similarity index 100% rename from openmp/libomptarget/test/api/omp_dynamic_shared_memory_mixed_nvptx.c rename to offload/test/api/omp_dynamic_shared_memory_mixed_nvptx.c diff --git a/openmp/libomptarget/test/api/omp_env_vars.c b/offload/test/api/omp_env_vars.c similarity index 100% rename from openmp/libomptarget/test/api/omp_env_vars.c rename to offload/test/api/omp_env_vars.c diff --git a/openmp/libomptarget/test/api/omp_get_device_num.c b/offload/test/api/omp_get_device_num.c similarity index 100% rename from openmp/libomptarget/test/api/omp_get_device_num.c rename to offload/test/api/omp_get_device_num.c diff --git a/openmp/libomptarget/test/api/omp_get_mapped_ptr.c b/offload/test/api/omp_get_mapped_ptr.c similarity index 100% rename from openmp/libomptarget/test/api/omp_get_mapped_ptr.c rename to offload/test/api/omp_get_mapped_ptr.c diff --git a/openmp/libomptarget/test/api/omp_get_num_devices.c b/offload/test/api/omp_get_num_devices.c similarity index 100% rename from openmp/libomptarget/test/api/omp_get_num_devices.c rename to offload/test/api/omp_get_num_devices.c diff --git a/openmp/libomptarget/test/api/omp_get_num_devices_with_empty_target.c b/offload/test/api/omp_get_num_devices_with_empty_target.c similarity index 100% rename from openmp/libomptarget/test/api/omp_get_num_devices_with_empty_target.c rename to offload/test/api/omp_get_num_devices_with_empty_target.c diff --git a/openmp/libomptarget/test/api/omp_get_num_procs.c b/offload/test/api/omp_get_num_procs.c similarity index 100% rename from openmp/libomptarget/test/api/omp_get_num_procs.c rename to offload/test/api/omp_get_num_procs.c diff --git a/openmp/libomptarget/test/api/omp_host_pinned_memory.c b/offload/test/api/omp_host_pinned_memory.c similarity index 100% rename from openmp/libomptarget/test/api/omp_host_pinned_memory.c rename to offload/test/api/omp_host_pinned_memory.c diff --git a/openmp/libomptarget/test/api/omp_host_pinned_memory_alloc.c b/offload/test/api/omp_host_pinned_memory_alloc.c similarity index 100% rename from openmp/libomptarget/test/api/omp_host_pinned_memory_alloc.c rename to offload/test/api/omp_host_pinned_memory_alloc.c diff --git a/openmp/libomptarget/test/api/omp_indirect_call.c b/offload/test/api/omp_indirect_call.c similarity index 100% rename from openmp/libomptarget/test/api/omp_indirect_call.c rename to offload/test/api/omp_indirect_call.c diff --git a/openmp/libomptarget/test/api/omp_target_memcpy_async1.c b/offload/test/api/omp_target_memcpy_async1.c similarity index 100% rename from openmp/libomptarget/test/api/omp_target_memcpy_async1.c rename to offload/test/api/omp_target_memcpy_async1.c diff --git a/openmp/libomptarget/test/api/omp_target_memcpy_async2.c b/offload/test/api/omp_target_memcpy_async2.c similarity index 100% rename from openmp/libomptarget/test/api/omp_target_memcpy_async2.c rename to offload/test/api/omp_target_memcpy_async2.c diff --git a/openmp/libomptarget/test/api/omp_target_memcpy_rect_async1.c b/offload/test/api/omp_target_memcpy_rect_async1.c similarity index 100% rename from openmp/libomptarget/test/api/omp_target_memcpy_rect_async1.c rename to offload/test/api/omp_target_memcpy_rect_async1.c diff --git a/openmp/libomptarget/test/api/omp_target_memcpy_rect_async2.c b/offload/test/api/omp_target_memcpy_rect_async2.c similarity index 100% rename from openmp/libomptarget/test/api/omp_target_memcpy_rect_async2.c rename to offload/test/api/omp_target_memcpy_rect_async2.c diff --git a/openmp/libomptarget/test/api/omp_target_memset.c b/offload/test/api/omp_target_memset.c similarity index 100% rename from openmp/libomptarget/test/api/omp_target_memset.c rename to offload/test/api/omp_target_memset.c diff --git a/openmp/libomptarget/test/api/ompx_3d.c b/offload/test/api/ompx_3d.c similarity index 100% rename from openmp/libomptarget/test/api/ompx_3d.c rename to offload/test/api/ompx_3d.c diff --git a/openmp/libomptarget/test/api/ompx_3d.cpp b/offload/test/api/ompx_3d.cpp similarity index 100% rename from openmp/libomptarget/test/api/ompx_3d.cpp rename to offload/test/api/ompx_3d.cpp diff --git a/openmp/libomptarget/test/api/ompx_sync.c b/offload/test/api/ompx_sync.c similarity index 100% rename from openmp/libomptarget/test/api/ompx_sync.c rename to offload/test/api/ompx_sync.c diff --git a/openmp/libomptarget/test/api/ompx_sync.cpp b/offload/test/api/ompx_sync.cpp similarity index 100% rename from openmp/libomptarget/test/api/ompx_sync.cpp rename to offload/test/api/ompx_sync.cpp diff --git a/openmp/libomptarget/test/env/base_ptr_ref_count.c b/offload/test/env/base_ptr_ref_count.c similarity index 100% rename from openmp/libomptarget/test/env/base_ptr_ref_count.c rename to offload/test/env/base_ptr_ref_count.c diff --git a/openmp/libomptarget/test/env/omp_target_debug.c b/offload/test/env/omp_target_debug.c similarity index 100% rename from openmp/libomptarget/test/env/omp_target_debug.c rename to offload/test/env/omp_target_debug.c diff --git a/openmp/libomptarget/test/jit/empty_kernel.inc b/offload/test/jit/empty_kernel.inc similarity index 100% rename from openmp/libomptarget/test/jit/empty_kernel.inc rename to offload/test/jit/empty_kernel.inc diff --git a/openmp/libomptarget/test/jit/empty_kernel_lvl1.c b/offload/test/jit/empty_kernel_lvl1.c similarity index 100% rename from openmp/libomptarget/test/jit/empty_kernel_lvl1.c rename to offload/test/jit/empty_kernel_lvl1.c diff --git a/openmp/libomptarget/test/jit/empty_kernel_lvl2.c b/offload/test/jit/empty_kernel_lvl2.c similarity index 100% rename from openmp/libomptarget/test/jit/empty_kernel_lvl2.c rename to offload/test/jit/empty_kernel_lvl2.c diff --git a/openmp/libomptarget/test/jit/type_punning.c b/offload/test/jit/type_punning.c similarity index 100% rename from openmp/libomptarget/test/jit/type_punning.c rename to offload/test/jit/type_punning.c diff --git a/openmp/libomptarget/test/libc/assert.c b/offload/test/libc/assert.c similarity index 100% rename from openmp/libomptarget/test/libc/assert.c rename to offload/test/libc/assert.c diff --git a/openmp/libomptarget/test/libc/fwrite.c b/offload/test/libc/fwrite.c similarity index 100% rename from openmp/libomptarget/test/libc/fwrite.c rename to offload/test/libc/fwrite.c diff --git a/openmp/libomptarget/test/libc/global_ctor_dtor.cpp b/offload/test/libc/global_ctor_dtor.cpp similarity index 100% rename from openmp/libomptarget/test/libc/global_ctor_dtor.cpp rename to offload/test/libc/global_ctor_dtor.cpp diff --git a/openmp/libomptarget/test/libc/host_call.c b/offload/test/libc/host_call.c similarity index 100% rename from openmp/libomptarget/test/libc/host_call.c rename to offload/test/libc/host_call.c diff --git a/openmp/libomptarget/test/libc/malloc.c b/offload/test/libc/malloc.c similarity index 100% rename from openmp/libomptarget/test/libc/malloc.c rename to offload/test/libc/malloc.c diff --git a/openmp/libomptarget/test/libc/puts.c b/offload/test/libc/puts.c similarity index 100% rename from openmp/libomptarget/test/libc/puts.c rename to offload/test/libc/puts.c diff --git a/openmp/libomptarget/test/lit.cfg b/offload/test/lit.cfg similarity index 100% rename from openmp/libomptarget/test/lit.cfg rename to offload/test/lit.cfg diff --git a/openmp/libomptarget/test/lit.site.cfg.in b/offload/test/lit.site.cfg.in similarity index 100% rename from openmp/libomptarget/test/lit.site.cfg.in rename to offload/test/lit.site.cfg.in diff --git a/openmp/libomptarget/test/mapping/alloc_fail.c b/offload/test/mapping/alloc_fail.c similarity index 100% rename from openmp/libomptarget/test/mapping/alloc_fail.c rename to offload/test/mapping/alloc_fail.c diff --git a/openmp/libomptarget/test/mapping/array_section_implicit_capture.c b/offload/test/mapping/array_section_implicit_capture.c similarity index 100% rename from openmp/libomptarget/test/mapping/array_section_implicit_capture.c rename to offload/test/mapping/array_section_implicit_capture.c diff --git a/openmp/libomptarget/test/mapping/array_section_use_device_ptr.c b/offload/test/mapping/array_section_use_device_ptr.c similarity index 100% rename from openmp/libomptarget/test/mapping/array_section_use_device_ptr.c rename to offload/test/mapping/array_section_use_device_ptr.c diff --git a/openmp/libomptarget/test/mapping/auto_zero_copy.cpp b/offload/test/mapping/auto_zero_copy.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/auto_zero_copy.cpp rename to offload/test/mapping/auto_zero_copy.cpp diff --git a/openmp/libomptarget/test/mapping/auto_zero_copy_apu.cpp b/offload/test/mapping/auto_zero_copy_apu.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/auto_zero_copy_apu.cpp rename to offload/test/mapping/auto_zero_copy_apu.cpp diff --git a/openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp b/offload/test/mapping/auto_zero_copy_globals.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp rename to offload/test/mapping/auto_zero_copy_globals.cpp diff --git a/openmp/libomptarget/test/mapping/data_absent_at_exit.c b/offload/test/mapping/data_absent_at_exit.c similarity index 100% rename from openmp/libomptarget/test/mapping/data_absent_at_exit.c rename to offload/test/mapping/data_absent_at_exit.c diff --git a/openmp/libomptarget/test/mapping/data_member_ref.cpp b/offload/test/mapping/data_member_ref.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/data_member_ref.cpp rename to offload/test/mapping/data_member_ref.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_api.cpp b/offload/test/mapping/declare_mapper_api.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_api.cpp rename to offload/test/mapping/declare_mapper_api.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers.cpp rename to offload/test/mapping/declare_mapper_nested_default_mappers.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_array.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers_array.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_array.cpp rename to offload/test/mapping/declare_mapper_nested_default_mappers_array.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_array_subscript.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers_array_subscript.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_array_subscript.cpp rename to offload/test/mapping/declare_mapper_nested_default_mappers_array_subscript.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_complex_structure.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers_complex_structure.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_complex_structure.cpp rename to offload/test/mapping/declare_mapper_nested_default_mappers_complex_structure.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_ptr_subscript.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers_ptr_subscript.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_ptr_subscript.cpp rename to offload/test/mapping/declare_mapper_nested_default_mappers_ptr_subscript.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_var.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers_var.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_default_mappers_var.cpp rename to offload/test/mapping/declare_mapper_nested_default_mappers_var.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_nested_mappers.cpp b/offload/test/mapping/declare_mapper_nested_mappers.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_nested_mappers.cpp rename to offload/test/mapping/declare_mapper_nested_mappers.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_target.cpp b/offload/test/mapping/declare_mapper_target.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_target.cpp rename to offload/test/mapping/declare_mapper_target.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_target_data.cpp b/offload/test/mapping/declare_mapper_target_data.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_target_data.cpp rename to offload/test/mapping/declare_mapper_target_data.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_target_data_enter_exit.cpp b/offload/test/mapping/declare_mapper_target_data_enter_exit.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_target_data_enter_exit.cpp rename to offload/test/mapping/declare_mapper_target_data_enter_exit.cpp diff --git a/openmp/libomptarget/test/mapping/declare_mapper_target_update.cpp b/offload/test/mapping/declare_mapper_target_update.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/declare_mapper_target_update.cpp rename to offload/test/mapping/declare_mapper_target_update.cpp diff --git a/openmp/libomptarget/test/mapping/delete_inf_refcount.c b/offload/test/mapping/delete_inf_refcount.c similarity index 100% rename from openmp/libomptarget/test/mapping/delete_inf_refcount.c rename to offload/test/mapping/delete_inf_refcount.c diff --git a/openmp/libomptarget/test/mapping/device_ptr_update.c b/offload/test/mapping/device_ptr_update.c similarity index 100% rename from openmp/libomptarget/test/mapping/device_ptr_update.c rename to offload/test/mapping/device_ptr_update.c diff --git a/openmp/libomptarget/test/mapping/firstprivate_aligned.cpp b/offload/test/mapping/firstprivate_aligned.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/firstprivate_aligned.cpp rename to offload/test/mapping/firstprivate_aligned.cpp diff --git a/openmp/libomptarget/test/mapping/has_device_addr.cpp b/offload/test/mapping/has_device_addr.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/has_device_addr.cpp rename to offload/test/mapping/has_device_addr.cpp diff --git a/openmp/libomptarget/test/mapping/implicit_device_ptr.c b/offload/test/mapping/implicit_device_ptr.c similarity index 100% rename from openmp/libomptarget/test/mapping/implicit_device_ptr.c rename to offload/test/mapping/implicit_device_ptr.c diff --git a/openmp/libomptarget/test/mapping/is_device_ptr.cpp b/offload/test/mapping/is_device_ptr.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/is_device_ptr.cpp rename to offload/test/mapping/is_device_ptr.cpp diff --git a/openmp/libomptarget/test/mapping/lambda_by_value.cpp b/offload/test/mapping/lambda_by_value.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/lambda_by_value.cpp rename to offload/test/mapping/lambda_by_value.cpp diff --git a/openmp/libomptarget/test/mapping/lambda_mapping.cpp b/offload/test/mapping/lambda_mapping.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/lambda_mapping.cpp rename to offload/test/mapping/lambda_mapping.cpp diff --git a/openmp/libomptarget/test/mapping/low_alignment.c b/offload/test/mapping/low_alignment.c similarity index 100% rename from openmp/libomptarget/test/mapping/low_alignment.c rename to offload/test/mapping/low_alignment.c diff --git a/openmp/libomptarget/test/mapping/map_back_race.cpp b/offload/test/mapping/map_back_race.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/map_back_race.cpp rename to offload/test/mapping/map_back_race.cpp diff --git a/openmp/libomptarget/test/mapping/ompx_hold/omp_target_disassociate_ptr.c b/offload/test/mapping/ompx_hold/omp_target_disassociate_ptr.c similarity index 100% rename from openmp/libomptarget/test/mapping/ompx_hold/omp_target_disassociate_ptr.c rename to offload/test/mapping/ompx_hold/omp_target_disassociate_ptr.c diff --git a/openmp/libomptarget/test/mapping/ompx_hold/struct.c b/offload/test/mapping/ompx_hold/struct.c similarity index 100% rename from openmp/libomptarget/test/mapping/ompx_hold/struct.c rename to offload/test/mapping/ompx_hold/struct.c diff --git a/openmp/libomptarget/test/mapping/ompx_hold/target-data.c b/offload/test/mapping/ompx_hold/target-data.c similarity index 100% rename from openmp/libomptarget/test/mapping/ompx_hold/target-data.c rename to offload/test/mapping/ompx_hold/target-data.c diff --git a/openmp/libomptarget/test/mapping/ompx_hold/target.c b/offload/test/mapping/ompx_hold/target.c similarity index 100% rename from openmp/libomptarget/test/mapping/ompx_hold/target.c rename to offload/test/mapping/ompx_hold/target.c diff --git a/openmp/libomptarget/test/mapping/padding_not_mapped.c b/offload/test/mapping/padding_not_mapped.c similarity index 100% rename from openmp/libomptarget/test/mapping/padding_not_mapped.c rename to offload/test/mapping/padding_not_mapped.c diff --git a/openmp/libomptarget/test/mapping/power_of_two_alignment.c b/offload/test/mapping/power_of_two_alignment.c similarity index 100% rename from openmp/libomptarget/test/mapping/power_of_two_alignment.c rename to offload/test/mapping/power_of_two_alignment.c diff --git a/openmp/libomptarget/test/mapping/pr38704.c b/offload/test/mapping/pr38704.c similarity index 100% rename from openmp/libomptarget/test/mapping/pr38704.c rename to offload/test/mapping/pr38704.c diff --git a/openmp/libomptarget/test/mapping/prelock.cpp b/offload/test/mapping/prelock.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/prelock.cpp rename to offload/test/mapping/prelock.cpp diff --git a/openmp/libomptarget/test/mapping/present/target.c b/offload/test/mapping/present/target.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target.c rename to offload/test/mapping/present/target.c diff --git a/openmp/libomptarget/test/mapping/present/target_array_extension.c b/offload/test/mapping/present/target_array_extension.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_array_extension.c rename to offload/test/mapping/present/target_array_extension.c diff --git a/openmp/libomptarget/test/mapping/present/target_data.c b/offload/test/mapping/present/target_data.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_data.c rename to offload/test/mapping/present/target_data.c diff --git a/openmp/libomptarget/test/mapping/present/target_data_array_extension.c b/offload/test/mapping/present/target_data_array_extension.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_data_array_extension.c rename to offload/test/mapping/present/target_data_array_extension.c diff --git a/openmp/libomptarget/test/mapping/present/target_data_at_exit.c b/offload/test/mapping/present/target_data_at_exit.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_data_at_exit.c rename to offload/test/mapping/present/target_data_at_exit.c diff --git a/openmp/libomptarget/test/mapping/present/target_enter_data.c b/offload/test/mapping/present/target_enter_data.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_enter_data.c rename to offload/test/mapping/present/target_enter_data.c diff --git a/openmp/libomptarget/test/mapping/present/target_exit_data_delete.c b/offload/test/mapping/present/target_exit_data_delete.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_exit_data_delete.c rename to offload/test/mapping/present/target_exit_data_delete.c diff --git a/openmp/libomptarget/test/mapping/present/target_exit_data_release.c b/offload/test/mapping/present/target_exit_data_release.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_exit_data_release.c rename to offload/test/mapping/present/target_exit_data_release.c diff --git a/openmp/libomptarget/test/mapping/present/target_update.c b/offload/test/mapping/present/target_update.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_update.c rename to offload/test/mapping/present/target_update.c diff --git a/openmp/libomptarget/test/mapping/present/target_update_array_extension.c b/offload/test/mapping/present/target_update_array_extension.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/target_update_array_extension.c rename to offload/test/mapping/present/target_update_array_extension.c diff --git a/openmp/libomptarget/test/mapping/present/unified_shared_memory.c b/offload/test/mapping/present/unified_shared_memory.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/unified_shared_memory.c rename to offload/test/mapping/present/unified_shared_memory.c diff --git a/openmp/libomptarget/test/mapping/present/zero_length_array_section.c b/offload/test/mapping/present/zero_length_array_section.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/zero_length_array_section.c rename to offload/test/mapping/present/zero_length_array_section.c diff --git a/openmp/libomptarget/test/mapping/present/zero_length_array_section_exit.c b/offload/test/mapping/present/zero_length_array_section_exit.c similarity index 100% rename from openmp/libomptarget/test/mapping/present/zero_length_array_section_exit.c rename to offload/test/mapping/present/zero_length_array_section_exit.c diff --git a/openmp/libomptarget/test/mapping/private_mapping.c b/offload/test/mapping/private_mapping.c similarity index 100% rename from openmp/libomptarget/test/mapping/private_mapping.c rename to offload/test/mapping/private_mapping.c diff --git a/openmp/libomptarget/test/mapping/ptr_and_obj_motion.c b/offload/test/mapping/ptr_and_obj_motion.c similarity index 100% rename from openmp/libomptarget/test/mapping/ptr_and_obj_motion.c rename to offload/test/mapping/ptr_and_obj_motion.c diff --git a/openmp/libomptarget/test/mapping/reduction_implicit_map.cpp b/offload/test/mapping/reduction_implicit_map.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/reduction_implicit_map.cpp rename to offload/test/mapping/reduction_implicit_map.cpp diff --git a/openmp/libomptarget/test/mapping/target_data_array_extension_at_exit.c b/offload/test/mapping/target_data_array_extension_at_exit.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_data_array_extension_at_exit.c rename to offload/test/mapping/target_data_array_extension_at_exit.c diff --git a/openmp/libomptarget/test/mapping/target_derefence_array_pointrs.cpp b/offload/test/mapping/target_derefence_array_pointrs.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/target_derefence_array_pointrs.cpp rename to offload/test/mapping/target_derefence_array_pointrs.cpp diff --git a/openmp/libomptarget/test/mapping/target_has_device_addr.c b/offload/test/mapping/target_has_device_addr.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_has_device_addr.c rename to offload/test/mapping/target_has_device_addr.c diff --git a/openmp/libomptarget/test/mapping/target_implicit_partial_map.c b/offload/test/mapping/target_implicit_partial_map.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_implicit_partial_map.c rename to offload/test/mapping/target_implicit_partial_map.c diff --git a/openmp/libomptarget/test/mapping/target_map_for_member_data.cpp b/offload/test/mapping/target_map_for_member_data.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/target_map_for_member_data.cpp rename to offload/test/mapping/target_map_for_member_data.cpp diff --git a/openmp/libomptarget/test/mapping/target_pointers_members_map.cpp b/offload/test/mapping/target_pointers_members_map.cpp similarity index 100% rename from openmp/libomptarget/test/mapping/target_pointers_members_map.cpp rename to offload/test/mapping/target_pointers_members_map.cpp diff --git a/openmp/libomptarget/test/mapping/target_update_array_extension.c b/offload/test/mapping/target_update_array_extension.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_update_array_extension.c rename to offload/test/mapping/target_update_array_extension.c diff --git a/openmp/libomptarget/test/mapping/target_use_device_addr.c b/offload/test/mapping/target_use_device_addr.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_use_device_addr.c rename to offload/test/mapping/target_use_device_addr.c diff --git a/openmp/libomptarget/test/mapping/target_uses_allocator.c b/offload/test/mapping/target_uses_allocator.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_uses_allocator.c rename to offload/test/mapping/target_uses_allocator.c diff --git a/openmp/libomptarget/test/mapping/target_wrong_use_device_addr.c b/offload/test/mapping/target_wrong_use_device_addr.c similarity index 100% rename from openmp/libomptarget/test/mapping/target_wrong_use_device_addr.c rename to offload/test/mapping/target_wrong_use_device_addr.c diff --git a/openmp/libomptarget/test/offloading/assert.cpp b/offload/test/offloading/assert.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/assert.cpp rename to offload/test/offloading/assert.cpp diff --git a/openmp/libomptarget/test/offloading/atomic-compare-signedness.c b/offload/test/offloading/atomic-compare-signedness.c similarity index 100% rename from openmp/libomptarget/test/offloading/atomic-compare-signedness.c rename to offload/test/offloading/atomic-compare-signedness.c diff --git a/openmp/libomptarget/test/offloading/back2back_distribute.c b/offload/test/offloading/back2back_distribute.c similarity index 100% rename from openmp/libomptarget/test/offloading/back2back_distribute.c rename to offload/test/offloading/back2back_distribute.c diff --git a/openmp/libomptarget/test/offloading/barrier_fence.c b/offload/test/offloading/barrier_fence.c similarity index 100% rename from openmp/libomptarget/test/offloading/barrier_fence.c rename to offload/test/offloading/barrier_fence.c diff --git a/openmp/libomptarget/test/offloading/bug47654.cpp b/offload/test/offloading/bug47654.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/bug47654.cpp rename to offload/test/offloading/bug47654.cpp diff --git a/openmp/libomptarget/test/offloading/bug49021.cpp b/offload/test/offloading/bug49021.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/bug49021.cpp rename to offload/test/offloading/bug49021.cpp diff --git a/openmp/libomptarget/test/offloading/bug49334.cpp b/offload/test/offloading/bug49334.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/bug49334.cpp rename to offload/test/offloading/bug49334.cpp diff --git a/openmp/libomptarget/test/offloading/bug49779.cpp b/offload/test/offloading/bug49779.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/bug49779.cpp rename to offload/test/offloading/bug49779.cpp diff --git a/openmp/libomptarget/test/offloading/bug50022.cpp b/offload/test/offloading/bug50022.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/bug50022.cpp rename to offload/test/offloading/bug50022.cpp diff --git a/openmp/libomptarget/test/offloading/bug51781.c b/offload/test/offloading/bug51781.c similarity index 100% rename from openmp/libomptarget/test/offloading/bug51781.c rename to offload/test/offloading/bug51781.c diff --git a/openmp/libomptarget/test/offloading/bug51982.c b/offload/test/offloading/bug51982.c similarity index 100% rename from openmp/libomptarget/test/offloading/bug51982.c rename to offload/test/offloading/bug51982.c diff --git a/openmp/libomptarget/test/offloading/bug53727.cpp b/offload/test/offloading/bug53727.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/bug53727.cpp rename to offload/test/offloading/bug53727.cpp diff --git a/openmp/libomptarget/test/offloading/bug64959.c b/offload/test/offloading/bug64959.c similarity index 100% rename from openmp/libomptarget/test/offloading/bug64959.c rename to offload/test/offloading/bug64959.c diff --git a/openmp/libomptarget/test/offloading/bug64959_compile_only.c b/offload/test/offloading/bug64959_compile_only.c similarity index 100% rename from openmp/libomptarget/test/offloading/bug64959_compile_only.c rename to offload/test/offloading/bug64959_compile_only.c diff --git a/openmp/libomptarget/test/offloading/bug74582.c b/offload/test/offloading/bug74582.c similarity index 100% rename from openmp/libomptarget/test/offloading/bug74582.c rename to offload/test/offloading/bug74582.c diff --git a/openmp/libomptarget/test/offloading/complex_reduction.cpp b/offload/test/offloading/complex_reduction.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/complex_reduction.cpp rename to offload/test/offloading/complex_reduction.cpp diff --git a/openmp/libomptarget/test/offloading/ctor_dtor.cpp b/offload/test/offloading/ctor_dtor.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/ctor_dtor.cpp rename to offload/test/offloading/ctor_dtor.cpp diff --git a/openmp/libomptarget/test/offloading/cuda_no_devices.c b/offload/test/offloading/cuda_no_devices.c similarity index 100% rename from openmp/libomptarget/test/offloading/cuda_no_devices.c rename to offload/test/offloading/cuda_no_devices.c diff --git a/openmp/libomptarget/test/offloading/d2d_memcpy.c b/offload/test/offloading/d2d_memcpy.c similarity index 100% rename from openmp/libomptarget/test/offloading/d2d_memcpy.c rename to offload/test/offloading/d2d_memcpy.c diff --git a/openmp/libomptarget/test/offloading/d2d_memcpy_sync.c b/offload/test/offloading/d2d_memcpy_sync.c similarity index 100% rename from openmp/libomptarget/test/offloading/d2d_memcpy_sync.c rename to offload/test/offloading/d2d_memcpy_sync.c diff --git a/openmp/libomptarget/test/offloading/default_thread_limit.c b/offload/test/offloading/default_thread_limit.c similarity index 100% rename from openmp/libomptarget/test/offloading/default_thread_limit.c rename to offload/test/offloading/default_thread_limit.c diff --git a/openmp/libomptarget/test/offloading/dynamic_module.c b/offload/test/offloading/dynamic_module.c similarity index 100% rename from openmp/libomptarget/test/offloading/dynamic_module.c rename to offload/test/offloading/dynamic_module.c diff --git a/openmp/libomptarget/test/offloading/dynamic_module_load.c b/offload/test/offloading/dynamic_module_load.c similarity index 100% rename from openmp/libomptarget/test/offloading/dynamic_module_load.c rename to offload/test/offloading/dynamic_module_load.c diff --git a/openmp/libomptarget/test/offloading/extern.c b/offload/test/offloading/extern.c similarity index 100% rename from openmp/libomptarget/test/offloading/extern.c rename to offload/test/offloading/extern.c diff --git a/openmp/libomptarget/test/offloading/force-usm.cpp b/offload/test/offloading/force-usm.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/force-usm.cpp rename to offload/test/offloading/force-usm.cpp diff --git a/openmp/libomptarget/test/offloading/fortran/basic-target-parallel-do.f90 b/offload/test/offloading/fortran/basic-target-parallel-do.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic-target-parallel-do.f90 rename to offload/test/offloading/fortran/basic-target-parallel-do.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/basic-target-parallel-region.f90 b/offload/test/offloading/fortran/basic-target-parallel-region.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic-target-parallel-region.f90 rename to offload/test/offloading/fortran/basic-target-parallel-region.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/basic-target-region-1D-array-section.f90 b/offload/test/offloading/fortran/basic-target-region-1D-array-section.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic-target-region-1D-array-section.f90 rename to offload/test/offloading/fortran/basic-target-region-1D-array-section.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/basic-target-region-3D-array-section.f90 b/offload/test/offloading/fortran/basic-target-region-3D-array-section.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic-target-region-3D-array-section.f90 rename to offload/test/offloading/fortran/basic-target-region-3D-array-section.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/basic-target-region-3D-array.f90 b/offload/test/offloading/fortran/basic-target-region-3D-array.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic-target-region-3D-array.f90 rename to offload/test/offloading/fortran/basic-target-region-3D-array.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/basic_array.c b/offload/test/offloading/fortran/basic_array.c similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic_array.c rename to offload/test/offloading/fortran/basic_array.c diff --git a/openmp/libomptarget/test/offloading/fortran/basic_target_region.f90 b/offload/test/offloading/fortran/basic_target_region.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/basic_target_region.f90 rename to offload/test/offloading/fortran/basic_target_region.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/constant-arr-index.f90 b/offload/test/offloading/fortran/constant-arr-index.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/constant-arr-index.f90 rename to offload/test/offloading/fortran/constant-arr-index.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/declare-target-vars-in-target-region.f90 b/offload/test/offloading/fortran/declare-target-vars-in-target-region.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/declare-target-vars-in-target-region.f90 rename to offload/test/offloading/fortran/declare-target-vars-in-target-region.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/double-target-call-with-declare-target.f90 b/offload/test/offloading/fortran/double-target-call-with-declare-target.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/double-target-call-with-declare-target.f90 rename to offload/test/offloading/fortran/double-target-call-with-declare-target.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-allocatable-array-section-1d-bounds.f90 b/offload/test/offloading/fortran/target-map-allocatable-array-section-1d-bounds.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-allocatable-array-section-1d-bounds.f90 rename to offload/test/offloading/fortran/target-map-allocatable-array-section-1d-bounds.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-allocatable-array-section-3d-bounds.f90 b/offload/test/offloading/fortran/target-map-allocatable-array-section-3d-bounds.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-allocatable-array-section-3d-bounds.f90 rename to offload/test/offloading/fortran/target-map-allocatable-array-section-3d-bounds.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-allocatable-map-scopes.f90 b/offload/test/offloading/fortran/target-map-allocatable-map-scopes.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-allocatable-map-scopes.f90 rename to offload/test/offloading/fortran/target-map-allocatable-map-scopes.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-allocatables.f90 b/offload/test/offloading/fortran/target-map-enter-exit-allocatables.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-allocatables.f90 rename to offload/test/offloading/fortran/target-map-enter-exit-allocatables.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-2.f90 b/offload/test/offloading/fortran/target-map-enter-exit-array-2.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-2.f90 rename to offload/test/offloading/fortran/target-map-enter-exit-array-2.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 b/offload/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 rename to offload/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array.f90 b/offload/test/offloading/fortran/target-map-enter-exit-array.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array.f90 rename to offload/test/offloading/fortran/target-map-enter-exit-array.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-scalar.f90 b/offload/test/offloading/fortran/target-map-enter-exit-scalar.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-scalar.f90 rename to offload/test/offloading/fortran/target-map-enter-exit-scalar.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-pointer-scopes-enter-exit.f90 b/offload/test/offloading/fortran/target-map-pointer-scopes-enter-exit.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-pointer-scopes-enter-exit.f90 rename to offload/test/offloading/fortran/target-map-pointer-scopes-enter-exit.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-pointer-target-array-section-3d-bounds.f90 b/offload/test/offloading/fortran/target-map-pointer-target-array-section-3d-bounds.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-pointer-target-array-section-3d-bounds.f90 rename to offload/test/offloading/fortran/target-map-pointer-target-array-section-3d-bounds.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-pointer-target-scopes.f90 b/offload/test/offloading/fortran/target-map-pointer-target-scopes.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-map-pointer-target-scopes.f90 rename to offload/test/offloading/fortran/target-map-pointer-target-scopes.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-nested-target-data.f90 b/offload/test/offloading/fortran/target-nested-target-data.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-nested-target-data.f90 rename to offload/test/offloading/fortran/target-nested-target-data.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-parallel-do-collapse.f90 b/offload/test/offloading/fortran/target-parallel-do-collapse.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-parallel-do-collapse.f90 rename to offload/test/offloading/fortran/target-parallel-do-collapse.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target-region-implicit-array.f90 b/offload/test/offloading/fortran/target-region-implicit-array.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target-region-implicit-array.f90 rename to offload/test/offloading/fortran/target-region-implicit-array.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target_map_common_block.f90 b/offload/test/offloading/fortran/target_map_common_block.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target_map_common_block.f90 rename to offload/test/offloading/fortran/target_map_common_block.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target_map_common_block1.f90 b/offload/test/offloading/fortran/target_map_common_block1.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target_map_common_block1.f90 rename to offload/test/offloading/fortran/target_map_common_block1.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target_map_common_block2.f90 b/offload/test/offloading/fortran/target_map_common_block2.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target_map_common_block2.f90 rename to offload/test/offloading/fortran/target_map_common_block2.f90 diff --git a/openmp/libomptarget/test/offloading/fortran/target_update.f90 b/offload/test/offloading/fortran/target_update.f90 similarity index 100% rename from openmp/libomptarget/test/offloading/fortran/target_update.f90 rename to offload/test/offloading/fortran/target_update.f90 diff --git a/openmp/libomptarget/test/offloading/generic_multiple_parallel_regions.c b/offload/test/offloading/generic_multiple_parallel_regions.c similarity index 100% rename from openmp/libomptarget/test/offloading/generic_multiple_parallel_regions.c rename to offload/test/offloading/generic_multiple_parallel_regions.c diff --git a/openmp/libomptarget/test/offloading/global_constructor.cpp b/offload/test/offloading/global_constructor.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/global_constructor.cpp rename to offload/test/offloading/global_constructor.cpp diff --git a/openmp/libomptarget/test/offloading/host_as_target.c b/offload/test/offloading/host_as_target.c similarity index 100% rename from openmp/libomptarget/test/offloading/host_as_target.c rename to offload/test/offloading/host_as_target.c diff --git a/openmp/libomptarget/test/offloading/indirect_fp_mapping.c b/offload/test/offloading/indirect_fp_mapping.c similarity index 100% rename from openmp/libomptarget/test/offloading/indirect_fp_mapping.c rename to offload/test/offloading/indirect_fp_mapping.c diff --git a/openmp/libomptarget/test/offloading/info.c b/offload/test/offloading/info.c similarity index 100% rename from openmp/libomptarget/test/offloading/info.c rename to offload/test/offloading/info.c diff --git a/openmp/libomptarget/test/offloading/interop.c b/offload/test/offloading/interop.c similarity index 100% rename from openmp/libomptarget/test/offloading/interop.c rename to offload/test/offloading/interop.c diff --git a/openmp/libomptarget/test/offloading/lone_target_exit_data.c b/offload/test/offloading/lone_target_exit_data.c similarity index 100% rename from openmp/libomptarget/test/offloading/lone_target_exit_data.c rename to offload/test/offloading/lone_target_exit_data.c diff --git a/openmp/libomptarget/test/offloading/looptripcnt.c b/offload/test/offloading/looptripcnt.c similarity index 100% rename from openmp/libomptarget/test/offloading/looptripcnt.c rename to offload/test/offloading/looptripcnt.c diff --git a/openmp/libomptarget/test/offloading/malloc.c b/offload/test/offloading/malloc.c similarity index 100% rename from openmp/libomptarget/test/offloading/malloc.c rename to offload/test/offloading/malloc.c diff --git a/openmp/libomptarget/test/offloading/malloc_parallel.c b/offload/test/offloading/malloc_parallel.c similarity index 100% rename from openmp/libomptarget/test/offloading/malloc_parallel.c rename to offload/test/offloading/malloc_parallel.c diff --git a/openmp/libomptarget/test/offloading/mandatory_but_no_devices.c b/offload/test/offloading/mandatory_but_no_devices.c similarity index 100% rename from openmp/libomptarget/test/offloading/mandatory_but_no_devices.c rename to offload/test/offloading/mandatory_but_no_devices.c diff --git a/openmp/libomptarget/test/offloading/memory_manager.cpp b/offload/test/offloading/memory_manager.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/memory_manager.cpp rename to offload/test/offloading/memory_manager.cpp diff --git a/openmp/libomptarget/test/offloading/multiple_reductions_simple.c b/offload/test/offloading/multiple_reductions_simple.c similarity index 100% rename from openmp/libomptarget/test/offloading/multiple_reductions_simple.c rename to offload/test/offloading/multiple_reductions_simple.c diff --git a/openmp/libomptarget/test/offloading/non_contiguous_update.cpp b/offload/test/offloading/non_contiguous_update.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/non_contiguous_update.cpp rename to offload/test/offloading/non_contiguous_update.cpp diff --git a/openmp/libomptarget/test/offloading/offloading_success.c b/offload/test/offloading/offloading_success.c similarity index 100% rename from openmp/libomptarget/test/offloading/offloading_success.c rename to offload/test/offloading/offloading_success.c diff --git a/openmp/libomptarget/test/offloading/offloading_success.cpp b/offload/test/offloading/offloading_success.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/offloading_success.cpp rename to offload/test/offloading/offloading_success.cpp diff --git a/openmp/libomptarget/test/offloading/ompx_bare.c b/offload/test/offloading/ompx_bare.c similarity index 100% rename from openmp/libomptarget/test/offloading/ompx_bare.c rename to offload/test/offloading/ompx_bare.c diff --git a/openmp/libomptarget/test/offloading/ompx_coords.c b/offload/test/offloading/ompx_coords.c similarity index 100% rename from openmp/libomptarget/test/offloading/ompx_coords.c rename to offload/test/offloading/ompx_coords.c diff --git a/openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c b/offload/test/offloading/ompx_saxpy_mixed.c similarity index 100% rename from openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c rename to offload/test/offloading/ompx_saxpy_mixed.c diff --git a/openmp/libomptarget/test/offloading/parallel_offloading_map.cpp b/offload/test/offloading/parallel_offloading_map.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/parallel_offloading_map.cpp rename to offload/test/offloading/parallel_offloading_map.cpp diff --git a/openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp b/offload/test/offloading/parallel_target_teams_reduction.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp rename to offload/test/offloading/parallel_target_teams_reduction.cpp diff --git a/openmp/libomptarget/test/offloading/parallel_target_teams_reduction_max.cpp b/offload/test/offloading/parallel_target_teams_reduction_max.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/parallel_target_teams_reduction_max.cpp rename to offload/test/offloading/parallel_target_teams_reduction_max.cpp diff --git a/openmp/libomptarget/test/offloading/parallel_target_teams_reduction_min.cpp b/offload/test/offloading/parallel_target_teams_reduction_min.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/parallel_target_teams_reduction_min.cpp rename to offload/test/offloading/parallel_target_teams_reduction_min.cpp diff --git a/openmp/libomptarget/test/offloading/requires.c b/offload/test/offloading/requires.c similarity index 100% rename from openmp/libomptarget/test/offloading/requires.c rename to offload/test/offloading/requires.c diff --git a/openmp/libomptarget/test/offloading/runtime_init.c b/offload/test/offloading/runtime_init.c similarity index 100% rename from openmp/libomptarget/test/offloading/runtime_init.c rename to offload/test/offloading/runtime_init.c diff --git a/openmp/libomptarget/test/offloading/shared_lib_fp_mapping.c b/offload/test/offloading/shared_lib_fp_mapping.c similarity index 100% rename from openmp/libomptarget/test/offloading/shared_lib_fp_mapping.c rename to offload/test/offloading/shared_lib_fp_mapping.c diff --git a/openmp/libomptarget/test/offloading/small_trip_count.c b/offload/test/offloading/small_trip_count.c similarity index 100% rename from openmp/libomptarget/test/offloading/small_trip_count.c rename to offload/test/offloading/small_trip_count.c diff --git a/openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp b/offload/test/offloading/small_trip_count_thread_limit.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp rename to offload/test/offloading/small_trip_count_thread_limit.cpp diff --git a/openmp/libomptarget/test/offloading/spmdization.c b/offload/test/offloading/spmdization.c similarity index 100% rename from openmp/libomptarget/test/offloading/spmdization.c rename to offload/test/offloading/spmdization.c diff --git a/openmp/libomptarget/test/offloading/static_linking.c b/offload/test/offloading/static_linking.c similarity index 100% rename from openmp/libomptarget/test/offloading/static_linking.c rename to offload/test/offloading/static_linking.c diff --git a/openmp/libomptarget/test/offloading/std_complex_arithmetic.cpp b/offload/test/offloading/std_complex_arithmetic.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/std_complex_arithmetic.cpp rename to offload/test/offloading/std_complex_arithmetic.cpp diff --git a/openmp/libomptarget/test/offloading/struct_mapping_with_pointers.cpp b/offload/test/offloading/struct_mapping_with_pointers.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/struct_mapping_with_pointers.cpp rename to offload/test/offloading/struct_mapping_with_pointers.cpp diff --git a/openmp/libomptarget/test/offloading/target-teams-atomic.c b/offload/test/offloading/target-teams-atomic.c similarity index 100% rename from openmp/libomptarget/test/offloading/target-teams-atomic.c rename to offload/test/offloading/target-teams-atomic.c diff --git a/openmp/libomptarget/test/offloading/target-tile.c b/offload/test/offloading/target-tile.c similarity index 100% rename from openmp/libomptarget/test/offloading/target-tile.c rename to offload/test/offloading/target-tile.c diff --git a/openmp/libomptarget/test/offloading/target_constexpr_mapping.cpp b/offload/test/offloading/target_constexpr_mapping.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/target_constexpr_mapping.cpp rename to offload/test/offloading/target_constexpr_mapping.cpp diff --git a/openmp/libomptarget/test/offloading/target_critical_region.cpp b/offload/test/offloading/target_critical_region.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/target_critical_region.cpp rename to offload/test/offloading/target_critical_region.cpp diff --git a/openmp/libomptarget/test/offloading/target_depend_nowait.cpp b/offload/test/offloading/target_depend_nowait.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/target_depend_nowait.cpp rename to offload/test/offloading/target_depend_nowait.cpp diff --git a/openmp/libomptarget/test/offloading/target_map_for_member_data.cpp b/offload/test/offloading/target_map_for_member_data.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/target_map_for_member_data.cpp rename to offload/test/offloading/target_map_for_member_data.cpp diff --git a/openmp/libomptarget/test/offloading/target_nowait_target.cpp b/offload/test/offloading/target_nowait_target.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/target_nowait_target.cpp rename to offload/test/offloading/target_nowait_target.cpp diff --git a/openmp/libomptarget/test/offloading/task_in_reduction_target.c b/offload/test/offloading/task_in_reduction_target.c similarity index 100% rename from openmp/libomptarget/test/offloading/task_in_reduction_target.c rename to offload/test/offloading/task_in_reduction_target.c diff --git a/openmp/libomptarget/test/offloading/taskloop_offload_nowait.cpp b/offload/test/offloading/taskloop_offload_nowait.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/taskloop_offload_nowait.cpp rename to offload/test/offloading/taskloop_offload_nowait.cpp diff --git a/openmp/libomptarget/test/offloading/test_libc.cpp b/offload/test/offloading/test_libc.cpp similarity index 100% rename from openmp/libomptarget/test/offloading/test_libc.cpp rename to offload/test/offloading/test_libc.cpp diff --git a/openmp/libomptarget/test/offloading/thread_limit.c b/offload/test/offloading/thread_limit.c similarity index 100% rename from openmp/libomptarget/test/offloading/thread_limit.c rename to offload/test/offloading/thread_limit.c diff --git a/openmp/libomptarget/test/offloading/thread_state_1.c b/offload/test/offloading/thread_state_1.c similarity index 100% rename from openmp/libomptarget/test/offloading/thread_state_1.c rename to offload/test/offloading/thread_state_1.c diff --git a/openmp/libomptarget/test/offloading/thread_state_2.c b/offload/test/offloading/thread_state_2.c similarity index 100% rename from openmp/libomptarget/test/offloading/thread_state_2.c rename to offload/test/offloading/thread_state_2.c diff --git a/openmp/libomptarget/test/offloading/weak.c b/offload/test/offloading/weak.c similarity index 100% rename from openmp/libomptarget/test/offloading/weak.c rename to offload/test/offloading/weak.c diff --git a/openmp/libomptarget/test/offloading/workshare_chunk.c b/offload/test/offloading/workshare_chunk.c similarity index 100% rename from openmp/libomptarget/test/offloading/workshare_chunk.c rename to offload/test/offloading/workshare_chunk.c diff --git a/openmp/libomptarget/test/offloading/wtime.c b/offload/test/offloading/wtime.c similarity index 100% rename from openmp/libomptarget/test/offloading/wtime.c rename to offload/test/offloading/wtime.c diff --git a/openmp/libomptarget/test/ompt/callbacks.h b/offload/test/ompt/callbacks.h similarity index 100% rename from openmp/libomptarget/test/ompt/callbacks.h rename to offload/test/ompt/callbacks.h diff --git a/openmp/libomptarget/test/ompt/register_both.h b/offload/test/ompt/register_both.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_both.h rename to offload/test/ompt/register_both.h diff --git a/openmp/libomptarget/test/ompt/register_emi.h b/offload/test/ompt/register_emi.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_emi.h rename to offload/test/ompt/register_emi.h diff --git a/openmp/libomptarget/test/ompt/register_emi_map.h b/offload/test/ompt/register_emi_map.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_emi_map.h rename to offload/test/ompt/register_emi_map.h diff --git a/openmp/libomptarget/test/ompt/register_no_device_init.h b/offload/test/ompt/register_no_device_init.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_no_device_init.h rename to offload/test/ompt/register_no_device_init.h diff --git a/openmp/libomptarget/test/ompt/register_non_emi.h b/offload/test/ompt/register_non_emi.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_non_emi.h rename to offload/test/ompt/register_non_emi.h diff --git a/openmp/libomptarget/test/ompt/register_non_emi_map.h b/offload/test/ompt/register_non_emi_map.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_non_emi_map.h rename to offload/test/ompt/register_non_emi_map.h diff --git a/openmp/libomptarget/test/ompt/register_wrong_return.h b/offload/test/ompt/register_wrong_return.h similarity index 100% rename from openmp/libomptarget/test/ompt/register_wrong_return.h rename to offload/test/ompt/register_wrong_return.h diff --git a/openmp/libomptarget/test/ompt/target_memcpy.c b/offload/test/ompt/target_memcpy.c similarity index 100% rename from openmp/libomptarget/test/ompt/target_memcpy.c rename to offload/test/ompt/target_memcpy.c diff --git a/openmp/libomptarget/test/ompt/target_memcpy_emi.c b/offload/test/ompt/target_memcpy_emi.c similarity index 100% rename from openmp/libomptarget/test/ompt/target_memcpy_emi.c rename to offload/test/ompt/target_memcpy_emi.c diff --git a/openmp/libomptarget/test/ompt/veccopy.c b/offload/test/ompt/veccopy.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy.c rename to offload/test/ompt/veccopy.c diff --git a/openmp/libomptarget/test/ompt/veccopy_data.c b/offload/test/ompt/veccopy_data.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_data.c rename to offload/test/ompt/veccopy_data.c diff --git a/openmp/libomptarget/test/ompt/veccopy_disallow_both.c b/offload/test/ompt/veccopy_disallow_both.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_disallow_both.c rename to offload/test/ompt/veccopy_disallow_both.c diff --git a/openmp/libomptarget/test/ompt/veccopy_emi.c b/offload/test/ompt/veccopy_emi.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_emi.c rename to offload/test/ompt/veccopy_emi.c diff --git a/openmp/libomptarget/test/ompt/veccopy_emi_map.c b/offload/test/ompt/veccopy_emi_map.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_emi_map.c rename to offload/test/ompt/veccopy_emi_map.c diff --git a/openmp/libomptarget/test/ompt/veccopy_map.c b/offload/test/ompt/veccopy_map.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_map.c rename to offload/test/ompt/veccopy_map.c diff --git a/openmp/libomptarget/test/ompt/veccopy_no_device_init.c b/offload/test/ompt/veccopy_no_device_init.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_no_device_init.c rename to offload/test/ompt/veccopy_no_device_init.c diff --git a/openmp/libomptarget/test/ompt/veccopy_wrong_return.c b/offload/test/ompt/veccopy_wrong_return.c similarity index 100% rename from openmp/libomptarget/test/ompt/veccopy_wrong_return.c rename to offload/test/ompt/veccopy_wrong_return.c diff --git a/openmp/libomptarget/test/unified_shared_memory/api.c b/offload/test/unified_shared_memory/api.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/api.c rename to offload/test/unified_shared_memory/api.c diff --git a/openmp/libomptarget/test/unified_shared_memory/associate_ptr.c b/offload/test/unified_shared_memory/associate_ptr.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/associate_ptr.c rename to offload/test/unified_shared_memory/associate_ptr.c diff --git a/openmp/libomptarget/test/unified_shared_memory/close_enter_exit.c b/offload/test/unified_shared_memory/close_enter_exit.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/close_enter_exit.c rename to offload/test/unified_shared_memory/close_enter_exit.c diff --git a/openmp/libomptarget/test/unified_shared_memory/close_manual.c b/offload/test/unified_shared_memory/close_manual.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/close_manual.c rename to offload/test/unified_shared_memory/close_manual.c diff --git a/openmp/libomptarget/test/unified_shared_memory/close_member.c b/offload/test/unified_shared_memory/close_member.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/close_member.c rename to offload/test/unified_shared_memory/close_member.c diff --git a/openmp/libomptarget/test/unified_shared_memory/close_modifier.c b/offload/test/unified_shared_memory/close_modifier.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/close_modifier.c rename to offload/test/unified_shared_memory/close_modifier.c diff --git a/openmp/libomptarget/test/unified_shared_memory/shared_update.c b/offload/test/unified_shared_memory/shared_update.c similarity index 100% rename from openmp/libomptarget/test/unified_shared_memory/shared_update.c rename to offload/test/unified_shared_memory/shared_update.c diff --git a/openmp/libomptarget/tools/CMakeLists.txt b/offload/tools/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/tools/CMakeLists.txt rename to offload/tools/CMakeLists.txt diff --git a/openmp/libomptarget/tools/deviceinfo/CMakeLists.txt b/offload/tools/deviceinfo/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/tools/deviceinfo/CMakeLists.txt rename to offload/tools/deviceinfo/CMakeLists.txt diff --git a/openmp/libomptarget/tools/deviceinfo/llvm-omp-device-info.cpp b/offload/tools/deviceinfo/llvm-omp-device-info.cpp similarity index 100% rename from openmp/libomptarget/tools/deviceinfo/llvm-omp-device-info.cpp rename to offload/tools/deviceinfo/llvm-omp-device-info.cpp diff --git a/openmp/libomptarget/tools/kernelreplay/CMakeLists.txt b/offload/tools/kernelreplay/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/tools/kernelreplay/CMakeLists.txt rename to offload/tools/kernelreplay/CMakeLists.txt diff --git a/openmp/libomptarget/tools/kernelreplay/llvm-omp-kernel-replay.cpp b/offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp similarity index 100% rename from openmp/libomptarget/tools/kernelreplay/llvm-omp-kernel-replay.cpp rename to offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp diff --git a/openmp/libomptarget/unittests/CMakeLists.txt b/offload/unittests/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/unittests/CMakeLists.txt rename to offload/unittests/CMakeLists.txt diff --git a/openmp/libomptarget/unittests/Plugins/CMakeLists.txt b/offload/unittests/Plugins/CMakeLists.txt similarity index 100% rename from openmp/libomptarget/unittests/Plugins/CMakeLists.txt rename to offload/unittests/Plugins/CMakeLists.txt diff --git a/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp b/offload/unittests/Plugins/NextgenPluginsTest.cpp similarity index 100% rename from openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp rename to offload/unittests/Plugins/NextgenPluginsTest.cpp diff --git a/openmp/libomptarget/utils/generate_microtask_cases.py b/offload/utils/generate_microtask_cases.py similarity index 100% rename from openmp/libomptarget/utils/generate_microtask_cases.py rename to offload/utils/generate_microtask_cases.py diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt index 3c4ff76ad6d1..95f2425db3ee 100644 --- a/openmp/CMakeLists.txt +++ b/openmp/CMakeLists.txt @@ -113,7 +113,17 @@ option(OPENMP_ENABLE_LIBOMP_PROFILING "Enable time profiling for libomp." OFF) # Header install location if(${OPENMP_STANDALONE_BUILD}) - set(LIBOMP_HEADERS_INSTALL_PATH "${CMAKE_INSTALL_INCLUDEDIR}") + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + execute_process( + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${CMAKE_CXX_COMPILER} --print-resource-dir + RESULT_VARIABLE COMMAND_RETURN_CODE + OUTPUT_VARIABLE COMPILER_RESOURCE_DIR + ) + set(LIBOMP_HEADERS_INSTALL_PATH "${COMPILER_RESOURCE_DIR}/include") + else() + set(LIBOMP_HEADERS_INSTALL_PATH "${CMAKE_INSTALL_INCLUDEDIR}") + endif() else() include(GetClangResourceDir) get_clang_resource_dir(LIBOMP_HEADERS_INSTALL_PATH SUBDIR include) @@ -123,19 +133,6 @@ endif() # to enable time profiling support in the OpenMP runtime. add_subdirectory(runtime) -if (OPENMP_ENABLE_LIBOMPTARGET) - # Check that the library can actually be built. - if (APPLE OR WIN32) - message(FATAL_ERROR "libomptarget cannot be built on Windows and MacOS X!") - elseif (NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES) - message(FATAL_ERROR "Host compiler must support C++17 to build libomptarget!") - elseif (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) - message(FATAL_ERROR "libomptarget on 32-bit systems are not supported!") - endif() - - add_subdirectory(libomptarget) -endif() - set(ENABLE_OMPT_TOOLS ON) # Currently tools are not tested well on Windows or MacOS X. if (APPLE OR WIN32) @@ -148,6 +145,10 @@ if (OPENMP_ENABLE_OMPT_TOOLS) add_subdirectory(tools) endif() +# Propagate OMPT support to offload +set(LIBOMP_HAVE_OMPT_SUPPORT ${LIBOMP_HAVE_OMPT_SUPPORT} PARENT_SCOPE) +set(LIBOMP_OMP_TOOLS_INCLUDE_DIR ${LIBOMP_OMP_TOOLS_INCLUDE_DIR} PARENT_SCOPE) + option(OPENMP_MSVC_NAME_SCHEME "Build dll with MSVC naming scheme." OFF) # Build libompd.so diff --git a/openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp b/openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp deleted file mode 100644 index c170c2d73873..000000000000 --- a/openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// RUN: %libomptarget-compilexx-run-and-check-generic - -#include -#include - -#define N 10 - -int main() { - int *a = new __int32_t[N]; // mapped and released from device 0 - int *b = new __int32_t[2 * N]; // mapped to device 0 - - // clang-format off - // CHECK: Mapping tables after target enter data: - // CHECK-NEXT: omptarget device 0 info: OpenMP Host-Device pointer mappings after block - // CHECK-NEXT: omptarget device 0 info: Host Ptr Target Ptr Size (B) DynRefCount HoldRefCount Declaration - // CHECK-NEXT: omptarget device 0 info: {{(0x[0-9a-f]{16})}} {{(0x[0-9a-f]{16})}} {{[48]}}0 - // CHECK-NEXT: omptarget device 0 info: {{(0x[0-9a-f]{16})}} {{(0x[0-9a-f]{16})}} {{[48]}}0 -#pragma omp target enter data device(0) map(to : a[ : N]) -#pragma omp target enter data device(0) map(to : b[ : 2*N]) - // clang-format on - printf("Mapping tables after target enter data:\n"); - ompx_dump_mapping_tables(); - - // clang-format off - // CHECK: Mapping tables after target exit data for a: - // CHECK-NEXT: omptarget device 0 info: OpenMP Host-Device pointer mappings after block - // CHECK-NEXT: omptarget device 0 info: Host Ptr Target Ptr Size (B) DynRefCount HoldRefCount Declaration - // CHECK-NEXT: omptarget device 0 info: {{(0x[0-9a-f]{16})}} {{(0x[0-9a-f]{16})}} 80 -#pragma omp target exit data device(0) map(release : a[ : N]) - // clang-format on - printf("\nMapping tables after target exit data for a:\n"); - ompx_dump_mapping_tables(); - - return 0; -} diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt index 701c35150f30..a2468d04e60a 100644 --- a/openmp/runtime/src/CMakeLists.txt +++ b/openmp/runtime/src/CMakeLists.txt @@ -229,6 +229,7 @@ if(NOT LIBOMP_LIBRARY_DIR) else() set(LIBOMP_LIBRARY_DIR ${LIBOMP_LIBRARY_DIR} PARENT_SCOPE) endif() +set(LIBOMP_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(LIBOMP_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) # Add symbolic links to libomp @@ -241,7 +242,12 @@ if(NOT WIN32) WORKING_DIRECTORY ${LIBOMP_LIBRARY_DIR} ) endif() -set(LIBOMP_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) + +# Definitions for testing, for reuse when testing libomptarget-nvptx. +set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${LIBOMP_INCLUDE_DIR}" CACHE STRING + "Path to folder containing omp.h") +set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${LIBOMP_LIBRARY_DIR}" CACHE STRING + "Path to folder containing libomp.so, and libLLVMSupport.so with profiling enabled") # Create *.inc before compiling any sources # objects depend on : .inc files diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt index 6f24fbcccec9..fcc59c8fa1c3 100644 --- a/runtimes/CMakeLists.txt +++ b/runtimes/CMakeLists.txt @@ -21,7 +21,7 @@ list(INSERT CMAKE_MODULE_PATH 0 # We order libraries to mirror roughly how they are layered, except that compiler-rt can depend # on libc++, so we put it after. -set(LLVM_DEFAULT_RUNTIMES "libc;libunwind;libcxxabi;pstl;libcxx;compiler-rt;openmp") +set(LLVM_DEFAULT_RUNTIMES "libc;libunwind;libcxxabi;pstl;libcxx;compiler-rt;openmp;offload") set(LLVM_SUPPORTED_RUNTIMES "${LLVM_DEFAULT_RUNTIMES};llvm-libgcc") set(LLVM_ENABLE_RUNTIMES "" CACHE STRING "Semicolon-separated list of runtimes to build, or \"all\" (${LLVM_DEFAULT_RUNTIMES}). Supported runtimes are ${LLVM_SUPPORTED_RUNTIMES}.") -- GitLab From 8128d4b1229203c2ab20d3136410c149ea3652cf Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 22 Apr 2024 18:04:15 +0100 Subject: [PATCH 192/357] [RemoveDIs] Preserve debug info format in llvm-reduce (#89220) As the goal of LLVM reduce is to simplify the input file, it should not modify the debug info format - doing so by default would make it impossible to reduce an error that only occurs in the old format, for example (as briefly discussed at https://github.com/llvm/llvm-project/pull/86275). This patch uses the new "preserve debug info format" flag in llvm-reduce to prevent the input from being subtly transformed by llvm-reduce itself; this has no effect on any tools used for the interestingness check (i.e. if `opt` is invoked, it will still convert the reduced input to the new format by default), but simply ensures that the reduced file is strictly reduced rather than modified. --- .../tools/llvm-reduce/remove-dp-values.ll | 24 +++++++++++-------- llvm/tools/llvm-reduce/llvm-reduce.cpp | 15 ++---------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/llvm/test/tools/llvm-reduce/remove-dp-values.ll b/llvm/test/tools/llvm-reduce/remove-dp-values.ll index d137b279f4ea..ab9cff4ae768 100644 --- a/llvm/test/tools/llvm-reduce/remove-dp-values.ll +++ b/llvm/test/tools/llvm-reduce/remove-dp-values.ll @@ -1,17 +1,21 @@ -; RUN: llvm-reduce --abort-on-invalid-reduction --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t --try-experimental-debuginfo-iterators -; RUN: FileCheck --check-prefixes=CHECK-FINAL --input-file=%t %s --implicit-check-not=dbg.value +; RUN: llvm-reduce --abort-on-invalid-reduction --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck --check-prefixes=CHECK-FINAL --input-file=%t %s --implicit-check-not=#dbg_value + +; RUN: opt < %s -S --write-experimental-debuginfo=false > %t.intrinsics.ll +; RUN: llvm-reduce --abort-on-invalid-reduction --test FileCheck --test-arg --check-prefixes=INTRINSIC-INTERESTINGNESS --test-arg %s --test-arg --input-file %t.intrinsics.ll -o %t +; RUN: FileCheck --check-prefixes=INTRINSIC-FINAL --input-file=%t %s --implicit-check-not=#dbg_value ; Test that we can, in RemoveDIs mode / DbgVariableRecords mode (where variable location ; information isn't an instruction), remove one variable location assignment ; but not another. -; CHECK-INTERESTINGNESS: call void @llvm.dbg.value(metadata i32 %added, - -; CHECK-FINAL: declare void @llvm.dbg.value(metadata, -; CHECK-FINAL: %added = add -; CHECK-FINAL-NEXT: call void @llvm.dbg.value(metadata i32 %added, +; CHECK-INTERESTINGNESS: #dbg_value(i32 %added, +; INTRINSIC-INTERESTINGNESS: llvm.dbg.value(metadata i32 %added, -declare void @llvm.dbg.value(metadata, metadata, metadata) +; CHECK-FINAL: %added = add +; CHECK-FINAL-NEXT: #dbg_value(i32 %added, +; INTRINSIC-FINAL: %added = add +; INTRINSIC-FINAL-NEXT: llvm.dbg.value(metadata i32 %added, define i32 @main() !dbg !7 { entry: @@ -22,10 +26,10 @@ entry: store i32 0, ptr %interesting, align 4 %0 = load i32, ptr %interesting, align 4 %added = add nsw i32 %0, 1 - tail call void @llvm.dbg.value(metadata i32 %added, metadata !13, metadata !DIExpression()), !dbg !14 + #dbg_value(i32 %added, !13, !DIExpression(), !14) store i32 %added, ptr %interesting, align 4 %alsoloaded = load i32, ptr %interesting, align 4 - tail call void @llvm.dbg.value(metadata i32 %alsoloaded, metadata !13, metadata !DIExpression()), !dbg !14 + #dbg_value(i32 %alsoloaded, !13, !DIExpression(), !14) store i32 %alsoloaded, ptr %uninteresting2, align 4 ret i32 0 } diff --git a/llvm/tools/llvm-reduce/llvm-reduce.cpp b/llvm/tools/llvm-reduce/llvm-reduce.cpp index f913771487af..288a384c2ed4 100644 --- a/llvm/tools/llvm-reduce/llvm-reduce.cpp +++ b/llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -100,12 +100,7 @@ static cl::opt "of delta passes (default=5)"), cl::init(5), cl::cat(LLVMReduceOptions)); -static cl::opt TryUseNewDbgInfoFormat( - "try-experimental-debuginfo-iterators", - cl::desc("Enable debuginfo iterator positions, if they're built in"), - cl::init(false)); - -extern cl::opt UseNewDbgInfoFormat; +extern cl::opt PreserveInputDbgFormat; static codegen::RegisterCodeGenFlags CGF; @@ -146,17 +141,11 @@ static std::pair determineOutputType(bool IsMIR, int main(int Argc, char **Argv) { InitLLVM X(Argc, Argv); const StringRef ToolName(Argv[0]); + PreserveInputDbgFormat = cl::boolOrDefault::BOU_TRUE; cl::HideUnrelatedOptions({&LLVMReduceOptions, &getColorCategory()}); cl::ParseCommandLineOptions(Argc, Argv, "LLVM automatic testcase reducer.\n"); - // RemoveDIs debug-info transition: tests may request that we /try/ to use the - // new debug-info format. - if (TryUseNewDbgInfoFormat) { - // Turn the new debug-info format on. - UseNewDbgInfoFormat = true; - } - if (Argc == 1) { cl::PrintHelpMessage(); return 0; -- GitLab From 7c20576cc37ab6b078782caf7575dab4ef87b37c Mon Sep 17 00:00:00 2001 From: Iman Hosseini Date: Mon, 22 Apr 2024 18:16:59 +0100 Subject: [PATCH 193/357] [flang][cuda] fix parsing of cuda_kernel (#89613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix parsing of cuda_kernel: it missed a mlir::succeeded check and it was not setting up the `types` and causing mismatch between values and types of the grid/block (CUFKernelValues). @clementval --------- Co-authored-by: Iman Hosseini Co-authored-by: Valentin Clement (バレンタイン クレメン) --- flang/lib/Optimizer/Dialect/FIROps.cpp | 8 +++++++- flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index cc08f29a98f0..24af94f9b90a 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -3907,7 +3907,7 @@ mlir::ParseResult parseCUFKernelValues( if (mlir::succeeded(parser.parseOptionalStar())) return mlir::success(); - if (parser.parseOptionalLParen()) { + if (mlir::succeeded(parser.parseOptionalLParen())) { if (mlir::failed(parser.parseCommaSeparatedList( mlir::AsmParser::Delimiter::None, [&]() { if (parser.parseOperand(values.emplace_back())) @@ -3915,11 +3915,17 @@ mlir::ParseResult parseCUFKernelValues( return mlir::success(); }))) return mlir::failure(); + auto builder = parser.getBuilder(); + for (size_t i = 0; i < values.size(); i++) { + types.emplace_back(builder.getI32Type()); + } if (parser.parseRParen()) return mlir::failure(); } else { if (parser.parseOperand(values.emplace_back())) return mlir::failure(); + auto builder = parser.getBuilder(); + types.emplace_back(builder.getI32Type()); return mlir::success(); } return mlir::success(); diff --git a/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf b/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf index 6179e609db38..9b728cd19eb5 100644 --- a/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf +++ b/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf @@ -1,4 +1,5 @@ ! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir -fcuda %s -o - | fir-opt | FileCheck %s ! Test lowering of CUDA kernel loop directive. -- GitLab From 73ed2153beb529973741344874c0084d24c2f268 Mon Sep 17 00:00:00 2001 From: ZijunZhaoCCK Date: Mon, 22 Apr 2024 10:17:12 -0700 Subject: [PATCH 194/357] Carving out -Wformat warning about scoped enums into a subwarning (#88595) Make it part of -Wformat-pedantic. Fixes #81647 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaChecking.cpp | 11 ++++++++--- clang/test/FixIt/format-darwin-enum-class.cpp | 4 ++-- clang/test/FixIt/format.cpp | 6 ++++-- clang/test/SemaCXX/format-strings.cpp | 4 ++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index aea99680c79a..b5b351f3d30a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -251,6 +251,8 @@ Modified Compiler Flags f3 *c = (f3 *)x; } +- Carved out ``-Wformat`` warning about scoped enums into a subwarning and + make it controlled by ``-Wformat-pedantic``. Fixes #GH88595. Removed Compiler Flags ------------------------- diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2ef95741b3d6..51757f4cf727 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -12779,10 +12779,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // In this case, the expression could be printed using a different // specifier, but we've decided that the specifier is probably correct // and we should cast instead. Just use the normal warning message. + + unsigned Diag = + IsScopedEnum + ? diag::warn_format_conversion_argument_type_mismatch_pedantic + : diag::warn_format_conversion_argument_type_mismatch; + EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum - << E->getSourceRange(), + S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy + << IsEnum << E->getSourceRange(), E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints); } } diff --git a/clang/test/FixIt/format-darwin-enum-class.cpp b/clang/test/FixIt/format-darwin-enum-class.cpp index 5aa1a80d8614..6d0bb80e982d 100644 --- a/clang/test/FixIt/format-darwin-enum-class.cpp +++ b/clang/test/FixIt/format-darwin-enum-class.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wformat %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wformat-pedantic %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -fdiagnostics-parseable-fixits -Wformat-pedantic %s 2>&1 | FileCheck %s extern "C" int printf(const char * restrict, ...); diff --git a/clang/test/FixIt/format.cpp b/clang/test/FixIt/format.cpp index 4e6573a4f9e5..d663c0fb35e1 100644 --- a/clang/test/FixIt/format.cpp +++ b/clang/test/FixIt/format.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat %s -// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-pedantic %s +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat-pedantic %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s -verify=okay +// okay-no-diagnostics extern "C" int printf(const char *, ...); #define LOG(...) printf(__VA_ARGS__) diff --git a/clang/test/SemaCXX/format-strings.cpp b/clang/test/SemaCXX/format-strings.cpp index f554e905d645..48cf23999a94 100644 --- a/clang/test/SemaCXX/format-strings.cpp +++ b/clang/test/SemaCXX/format-strings.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -Wformat-pedantic -fblocks %s // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -Wformat-pedantic -fblocks -std=c++11 %s #include -- GitLab From 772863e3120fc770ae1ab458022284be04810097 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Mon, 22 Apr 2024 13:18:02 -0400 Subject: [PATCH 195/357] [SystemZ][NFC] Use new getPointerSize function (#89623) Use the new getPointerSize() function throughout the frame lowering class. --- .../lib/Target/SystemZ/SystemZFrameLowering.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index 2683470afc5e..fa20977ec018 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -181,7 +181,8 @@ bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots( StartSPOffset = Offset; } Offset -= SystemZMC::ELFCallFrameSize; - int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); + int FrameIdx = + MFFrame.CreateFixedSpillStackObject(getPointerSize(), Offset); CS.setFrameIdx(FrameIdx); } else CS.setFrameIdx(INT32_MAX); @@ -456,8 +457,10 @@ void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized( // are outside the reach of an unsigned 12-bit displacement. // Create 2 for the case where both addresses in an MVC are // out of range. - RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false)); - RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false)); + RS->addScavengingFrameIndex( + MFFrame.CreateStackObject(getPointerSize(), Align(8), false)); + RS->addScavengingFrameIndex( + MFFrame.CreateStackObject(getPointerSize(), Align(8), false)); } // If R6 is used as an argument register it is still callee saved. If it in @@ -870,7 +873,7 @@ int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex( if (!FI) { MachineFrameInfo &MFFrame = MF.getFrameInfo(); int Offset = getBackchainOffset(MF) - SystemZMC::ELFCallFrameSize; - FI = MFFrame.CreateFixedObject(8, Offset, false); + FI = MFFrame.CreateFixedObject(getPointerSize(), Offset, false); ZFI->setFramePointerSaveIndex(FI); } return FI; @@ -906,7 +909,7 @@ int SystemZXPLINKFrameLowering::getOrCreateFramePointerSaveIndex( int FI = ZFI->getFramePointerSaveIndex(); if (!FI) { MachineFrameInfo &MFFrame = MF.getFrameInfo(); - FI = MFFrame.CreateFixedObject(8, 0, false); + FI = MFFrame.CreateFixedObject(getPointerSize(), 0, false); MFFrame.setStackID(FI, TargetStackID::NoAlloc); ZFI->setFramePointerSaveIndex(FI); } @@ -1032,7 +1035,7 @@ bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots( // Non-volatile GPRs are saved in the dedicated register save area at // the bottom of the stack and are not truly part of the "normal" stack // frame. Mark the frame index as NoAlloc to indicate it as such. - unsigned RegSize = 8; + unsigned RegSize = getPointerSize(); int FrameIdx = (FPSI && Offset == 0) ? FPSI @@ -1302,7 +1305,7 @@ void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF, for (unsigned I = FixedRegs; I < SystemZ::XPLINK64NumArgGPRs; I++) { uint64_t StartOffset = MFFrame.getOffsetAdjustment() + MFFrame.getStackSize() + Regs.getCallFrameSize() + - getOffsetOfLocalArea() + I * 8; + getOffsetOfLocalArea() + I * getPointerSize(); unsigned Reg = GPRs[I]; BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STG)) .addReg(Reg) -- GitLab From 180cf4daec290e68aa4dd6dc14697add3e18bcec Mon Sep 17 00:00:00 2001 From: zibi2 <62662650+zibi2@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:24:47 -0400 Subject: [PATCH 196/357] [clangd] Fix unittests in TargetDeclTest bucket (#89630) This PR fixes the build errors for one of the `clangd` unit tests bucket similar to the following: ``` .../clang-tools-extra/clangd/unittests/FindTargetTests.cpp:430:29: error: passing no argument for the '...' parameter of a variadic macro is a C++20 extension [-Werror,-Wc++20-extensions] 430 | EXPECT_DECLS("AutoTypeLoc"); | ^ .../clang-tools-extra/clangd/unittests/FindTargetTests.cpp:98:9: note: macro 'EXPECT_DECLS' defined here 98 | #define EXPECT_DECLS(NodeType, ...) \ | ^ ``` This happens when using a build compiler with #84520. The fix is to include commas to compensate for empty vararg macro arguments in a few instances. --- .../clangd/unittests/FindTargetTests.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 0af6036734ba..799a549ff081 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -427,7 +427,7 @@ TEST_F(TargetDeclTest, Types) { [[auto]] X = S{}; )cpp"; // FIXME: deduced type missing in AST. https://llvm.org/PR42914 - EXPECT_DECLS("AutoTypeLoc"); + EXPECT_DECLS("AutoTypeLoc", ); Code = R"cpp( template @@ -727,13 +727,13 @@ TEST_F(TargetDeclTest, BuiltinTemplates) { template using make_integer_sequence = [[__make_integer_seq]]; )cpp"; - EXPECT_DECLS("TemplateSpecializationTypeLoc"); + EXPECT_DECLS("TemplateSpecializationTypeLoc", ); Code = R"cpp( template using type_pack_element = [[__type_pack_element]]; )cpp"; - EXPECT_DECLS("TemplateSpecializationTypeLoc"); + EXPECT_DECLS("TemplateSpecializationTypeLoc", ); } TEST_F(TargetDeclTest, MemberOfTemplate) { @@ -1018,7 +1018,7 @@ TEST_F(TargetDeclTest, DependentTypes) { typedef typename waldo::type::[[next]] type; }; )cpp"; - EXPECT_DECLS("DependentNameTypeLoc"); + EXPECT_DECLS("DependentNameTypeLoc", ); // Similar to above but using mutually recursive templates. Code = R"cpp( @@ -1035,7 +1035,7 @@ TEST_F(TargetDeclTest, DependentTypes) { using type = typename even::type::[[next]]; }; )cpp"; - EXPECT_DECLS("DependentNameTypeLoc"); + EXPECT_DECLS("DependentNameTypeLoc", ); } TEST_F(TargetDeclTest, TypedefCascade) { @@ -1263,14 +1263,14 @@ TEST_F(TargetDeclTest, ObjC) { + ([[id]])sharedInstance; @end )cpp"; - EXPECT_DECLS("TypedefTypeLoc"); + EXPECT_DECLS("TypedefTypeLoc", ); Code = R"cpp( @interface Foo + ([[instancetype]])sharedInstance; @end )cpp"; - EXPECT_DECLS("TypedefTypeLoc"); + EXPECT_DECLS("TypedefTypeLoc", ); } class FindExplicitReferencesTest : public ::testing::Test { -- GitLab From 9aa663bb9ef3dbab8ccc324ef3df5138aa458fbd Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Mon, 22 Apr 2024 19:26:33 +0200 Subject: [PATCH 197/357] [Clang] Fix __is_trivially_equaltiy_comparable documentation (#88528) Currently `__is_trivially_equality_comparable` is documented to return true if comparing the value representation is equivalent to calling the comparison operator, which is not quite what the trait actually checks. The traits actually checks that comparing the object representation is equivalent, which means that there cannot be padding bytes in the type. --- clang/docs/LanguageExtensions.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 3bead159c8f9..84fc4dee02fa 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1642,7 +1642,8 @@ The following type trait primitives are supported by Clang. Those traits marked were made trivially relocatable via the ``clang::trivial_abi`` attribute. * ``__is_trivially_equality_comparable`` (Clang): Returns true if comparing two objects of the provided type is known to be equivalent to comparing their - value representations. + object representations. Note that types containing padding bytes are never + trivially equality comparable. * ``__is_unbounded_array`` (C++, GNU, Microsoft, Embarcadero) * ``__is_union`` (C++, GNU, Microsoft, Embarcadero) * ``__is_unsigned`` (C++, Embarcadero): -- GitLab From a6c028299cbce9885dd3c3e989b2cb3273ba6e05 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 22 Apr 2024 10:32:47 -0700 Subject: [PATCH 198/357] [RISCV] Add extension information to RISCVFeatures.td. NFC (#89326) This adds a new RISCVExtension class that inherits from SubtargetFeature. This contains the major/minor version and whether the extension is experimental. The plan is to use this to generate the tables for RISCVISAInfo.cpp. The version numbers might not be accurate yet. If there are errors they will be fixed before they are used for anything. It will be easier to verify once the new tablegen backend is written to generate the RISCVISAInfo.cpp table. --- llvm/lib/Target/RISCV/RISCVFeatures.td | 810 +++++++++++++------------ 1 file changed, 425 insertions(+), 385 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 116e5a2ab734..b064191b838e 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -10,119 +10,157 @@ // RISC-V subtarget features and instruction predicates. //===----------------------------------------------------------------------===// +// Subclass of SubtargetFeature to be used when the feature is also a RISC-V +// extension. Extensions have a version and may be experimental. +// +// name - Name of the extension in lower case. +// major - Major version of extension. +// minor - Minor version of extension. +// desc - Description of extension. +// implies - Extensions or features implied by this extension. +// fieldname - name of field to create in RISCVSubtarget. By default replaces +// uses the record name by replacing Feature with Has. +// value - Value to assign to the field in RISCVSubtarget when this +// extension is enabled. Usually "true", but can be changed. +class RISCVExtension implies = [], + string fieldname = !subst("Feature", "Has", NAME), + string value = "true"> + : SubtargetFeature { + // MajorVersion - The major version for this extension. + int MajorVersion = major; + + // MinorVersion - The minor version for this extension. + int MinorVersion = minor; + + // Experimental - Does extension require -menable-experimental-extensions. + bit Experimental = false; +} + +// Version of RISCVExtension to be used for Experimental extensions. This +// sets the Experimental flag and prepends experimental- to the -mattr name. +class RISCVExperimentalExtension implies = [], + string fieldname = !subst("Feature", "Has", NAME), + string value = "true"> + : RISCVExtension<"experimental-"#name, major, minor, desc, implies, + fieldname, value> { + let Experimental = true; +} + // Integer Extensions def FeatureStdExtI - : SubtargetFeature<"i", "HasStdExtI", "true", - "'I' (Base Integer Instruction Set)">; + : RISCVExtension<"i", 2, 1, + "'I' (Base Integer Instruction Set)">; def FeatureStdExtE - : SubtargetFeature<"e", "HasStdExtE", "true", - "Implements RV{32,64}E (provides 16 rather than 32 GPRs)">; + : RISCVExtension<"e", 2, 0, + "Implements RV{32,64}E (provides 16 rather than 32 GPRs)">; def FeatureStdExtZic64b - : SubtargetFeature<"zic64b", "HasStdExtZic64b", "true", - "'Zic64b' (Cache Block Size Is 64 Bytes)">; + : RISCVExtension<"zic64b", 1, 0, + "'Zic64b' (Cache Block Size Is 64 Bytes)">; def FeatureStdExtZicbom - : SubtargetFeature<"zicbom", "HasStdExtZicbom", "true", - "'Zicbom' (Cache-Block Management Instructions)">; + : RISCVExtension<"zicbom", 1, 0, + "'Zicbom' (Cache-Block Management Instructions)">; def HasStdExtZicbom : Predicate<"Subtarget->hasStdExtZicbom()">, AssemblerPredicate<(all_of FeatureStdExtZicbom), "'Zicbom' (Cache-Block Management Instructions)">; def FeatureStdExtZicbop - : SubtargetFeature<"zicbop", "HasStdExtZicbop", "true", - "'Zicbop' (Cache-Block Prefetch Instructions)">; + : RISCVExtension<"zicbop", 1, 0, + "'Zicbop' (Cache-Block Prefetch Instructions)">; def HasStdExtZicbop : Predicate<"Subtarget->hasStdExtZicbop()">, AssemblerPredicate<(all_of FeatureStdExtZicbop), "'Zicbop' (Cache-Block Prefetch Instructions)">; def FeatureStdExtZicboz - : SubtargetFeature<"zicboz", "HasStdExtZicboz", "true", - "'Zicboz' (Cache-Block Zero Instructions)">; + : RISCVExtension<"zicboz", 1, 0, + "'Zicboz' (Cache-Block Zero Instructions)">; def HasStdExtZicboz : Predicate<"Subtarget->hasStdExtZicboz()">, AssemblerPredicate<(all_of FeatureStdExtZicboz), "'Zicboz' (Cache-Block Zero Instructions)">; def FeatureStdExtZiccamoa - : SubtargetFeature<"ziccamoa", "HasStdExtZiccamoa", "true", - "'Ziccamoa' (Main Memory Supports All Atomics in A)">; + : RISCVExtension<"ziccamoa", 1, 0, + "'Ziccamoa' (Main Memory Supports All Atomics in A)">; def FeatureStdExtZiccif - : SubtargetFeature<"ziccif", "HasStdExtZiccif", "true", - "'Ziccif' (Main Memory Supports Instruction Fetch with Atomicity Requirement)">; + : RISCVExtension<"ziccif", 1, 0, + "'Ziccif' (Main Memory Supports Instruction Fetch with Atomicity Requirement)">; def FeatureStdExtZicclsm - : SubtargetFeature<"zicclsm", "HasStdExtZicclsm", "true", - "'Zicclsm' (Main Memory Supports Misaligned Loads/Stores)">; + : RISCVExtension<"zicclsm", 1, 0, + "'Zicclsm' (Main Memory Supports Misaligned Loads/Stores)">; def FeatureStdExtZiccrse - : SubtargetFeature<"ziccrse", "HasStdExtZiccrse", "true", - "'Ziccrse' (Main Memory Supports Forward Progress on LR/SC Sequences)">; + : RISCVExtension<"ziccrse", 1, 0, + "'Ziccrse' (Main Memory Supports Forward Progress on LR/SC Sequences)">; def FeatureStdExtZicsr - : SubtargetFeature<"zicsr", "HasStdExtZicsr", "true", - "'zicsr' (CSRs)">; + : RISCVExtension<"zicsr", 2, 0, + "'zicsr' (CSRs)">; def HasStdExtZicsr : Predicate<"Subtarget->hasStdExtZicsr()">, AssemblerPredicate<(all_of FeatureStdExtZicsr), "'Zicsr' (CSRs)">; def FeatureStdExtZicntr - : SubtargetFeature<"zicntr", "HasStdExtZicntr", "true", - "'Zicntr' (Base Counters and Timers)", + : RISCVExtension<"zicntr", 2, 0, + "'Zicntr' (Base Counters and Timers)", [FeatureStdExtZicsr]>; def FeatureStdExtZicond - : SubtargetFeature<"zicond", "HasStdExtZicond", "true", - "'Zicond' (Integer Conditional Operations)">; + : RISCVExtension<"zicond", 1, 0, + "'Zicond' (Integer Conditional Operations)">; def HasStdExtZicond : Predicate<"Subtarget->hasStdExtZicond()">, AssemblerPredicate<(all_of FeatureStdExtZicond), "'Zicond' (Integer Conditional Operations)">; def FeatureStdExtZifencei - : SubtargetFeature<"zifencei", "HasStdExtZifencei", "true", - "'Zifencei' (fence.i)">; + : RISCVExtension<"zifencei", 2, 0, + "'Zifencei' (fence.i)">; def HasStdExtZifencei : Predicate<"Subtarget->hasStdExtZifencei()">, AssemblerPredicate<(all_of FeatureStdExtZifencei), "'Zifencei' (fence.i)">; def FeatureStdExtZihintpause - : SubtargetFeature<"zihintpause", "HasStdExtZihintpause", "true", - "'Zihintpause' (Pause Hint)">; + : RISCVExtension<"zihintpause", 2, 0, + "'Zihintpause' (Pause Hint)">; def HasStdExtZihintpause : Predicate<"Subtarget->hasStdExtZihintpause()">, AssemblerPredicate<(all_of FeatureStdExtZihintpause), "'Zihintpause' (Pause Hint)">; def FeatureStdExtZihintntl - : SubtargetFeature<"zihintntl", "HasStdExtZihintntl", "true", - "'Zihintntl' (Non-Temporal Locality Hints)">; + : RISCVExtension<"zihintntl", 1, 0, + "'Zihintntl' (Non-Temporal Locality Hints)">; def HasStdExtZihintntl : Predicate<"Subtarget->hasStdExtZihintntl()">, AssemblerPredicate<(all_of FeatureStdExtZihintntl), "'Zihintntl' (Non-Temporal Locality Hints)">; def FeatureStdExtZihpm - : SubtargetFeature<"zihpm", "HasStdExtZihpm", "true", - "'Zihpm' (Hardware Performance Counters)", - [FeatureStdExtZicsr]>; + : RISCVExtension<"zihpm", 2, 0, + "'Zihpm' (Hardware Performance Counters)", + [FeatureStdExtZicsr]>; -def FeatureStdExtZimop : SubtargetFeature<"zimop", "HasStdExtZimop", "true", - "'Zimop' (May-Be-Operations)">; +def FeatureStdExtZimop : RISCVExtension<"zimop", 1, 0, + "'Zimop' (May-Be-Operations)">; def HasStdExtZimop : Predicate<"Subtarget->hasStdExtZimop()">, AssemblerPredicate<(all_of FeatureStdExtZimop), "'Zimop' (May-Be-Operations)">; def FeatureStdExtZicfilp - : SubtargetFeature<"experimental-zicfilp", "HasStdExtZicfilp", "true", - "'Zicfilp' (Landing pad)">; + : RISCVExperimentalExtension<"zicfilp", 0, 4, + "'Zicfilp' (Landing pad)">; def HasStdExtZicfilp : Predicate<"Subtarget->hasStdExtZicfilp()">, AssemblerPredicate<(all_of FeatureStdExtZicfilp), "'Zicfilp' (Landing pad)">; def FeatureStdExtZicfiss - : SubtargetFeature<"experimental-zicfiss", "HasStdExtZicfiss", "true", - "'Zicfiss' (Shadow stack)", - [FeatureStdExtZicsr, FeatureStdExtZimop]>; + : RISCVExperimentalExtension<"zicfiss", 0, 4, + "'Zicfiss' (Shadow stack)", + [FeatureStdExtZicsr, FeatureStdExtZimop]>; def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">, AssemblerPredicate<(all_of FeatureStdExtZicfiss), "'Zicfiss' (Shadow stack)">; @@ -131,15 +169,15 @@ def NoHasStdExtZicfiss : Predicate<"!Subtarget->hasStdExtZicfiss()">; // Multiply Extensions def FeatureStdExtM - : SubtargetFeature<"m", "HasStdExtM", "true", - "'M' (Integer Multiplication and Division)">; + : RISCVExtension<"m", 2, 0, + "'M' (Integer Multiplication and Division)">; def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">, AssemblerPredicate<(all_of FeatureStdExtM), "'M' (Integer Multiplication and Division)">; def FeatureStdExtZmmul - : SubtargetFeature<"zmmul", "HasStdExtZmmul", "true", - "'Zmmul' (Integer Multiplication)">; + : RISCVExtension<"zmmul", 1, 0, + "'Zmmul' (Integer Multiplication)">; def HasStdExtMOrZmmul : Predicate<"Subtarget->hasStdExtM() || Subtarget->hasStdExtZmmul()">, @@ -150,29 +188,29 @@ def HasStdExtMOrZmmul // Atomic Extensions def FeatureStdExtA - : SubtargetFeature<"a", "HasStdExtA", "true", - "'A' (Atomic Instructions)">; + : RISCVExtension<"a", 2, 1, + "'A' (Atomic Instructions)">; def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">, AssemblerPredicate<(all_of FeatureStdExtA), "'A' (Atomic Instructions)">; def FeatureStdExtZtso - : SubtargetFeature<"experimental-ztso", "HasStdExtZtso", "true", - "'Ztso' (Memory Model - Total Store Order)">; + : RISCVExperimentalExtension<"ztso", 0, 1, + "'Ztso' (Memory Model - Total Store Order)">; def HasStdExtZtso : Predicate<"Subtarget->hasStdExtZtso()">, AssemblerPredicate<(all_of FeatureStdExtZtso), "'Ztso' (Memory Model - Total Store Order)">; def NotHasStdExtZtso : Predicate<"!Subtarget->hasStdExtZtso()">; -def FeatureStdExtZa64rs : SubtargetFeature<"za64rs", "HasStdExtZa64rs", "true", - "'Za64rs' (Reservation Set Size of at Most 64 Bytes)">; +def FeatureStdExtZa64rs : RISCVExtension<"za64rs", 1, 0, + "'Za64rs' (Reservation Set Size of at Most 64 Bytes)">; -def FeatureStdExtZa128rs : SubtargetFeature<"za128rs", "HasStdExtZa128rs", "true", - "'Za128rs' (Reservation Set Size of at Most 128 Bytes)">; +def FeatureStdExtZa128rs : RISCVExtension<"za128rs", 1, 0, + "'Za128rs' (Reservation Set Size of at Most 128 Bytes)">; def FeatureStdExtZaamo - : SubtargetFeature<"experimental-zaamo", "HasStdExtZaamo", "true", - "'Zaamo' (Atomic Memory Operations)">; + : RISCVExperimentalExtension<"zaamo", 0, 2, + "'Zaamo' (Atomic Memory Operations)">; def HasStdExtAOrZaamo : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasStdExtZaamo()">, AssemblerPredicate<(any_of FeatureStdExtA, FeatureStdExtZaamo), @@ -180,30 +218,30 @@ def HasStdExtAOrZaamo "'Zaamo' (Atomic Memory Operations)">; def FeatureStdExtZabha - : SubtargetFeature<"experimental-zabha", "HasStdExtZabha", "true", - "'Zabha' (Byte and Halfword Atomic Memory Operations)">; + : RISCVExperimentalExtension<"zabha", 1, 0, + "'Zabha' (Byte and Halfword Atomic Memory Operations)">; def HasStdExtZabha : Predicate<"Subtarget->hasStdExtZabha()">, AssemblerPredicate<(all_of FeatureStdExtZabha), "'Zabha' (Byte and Halfword Atomic Memory Operations)">; def FeatureStdExtZacas - : SubtargetFeature<"zacas", "HasStdExtZacas", "true", - "'Zacas' (Atomic Compare-And-Swap Instructions)">; + : RISCVExtension<"zacas", 1, 0, + "'Zacas' (Atomic Compare-And-Swap Instructions)">; def HasStdExtZacas : Predicate<"Subtarget->hasStdExtZacas()">, AssemblerPredicate<(all_of FeatureStdExtZacas), "'Zacas' (Atomic Compare-And-Swap Instructions)">; def NoStdExtZacas : Predicate<"!Subtarget->hasStdExtZacas()">; def FeatureStdExtZalasr - : SubtargetFeature<"experimental-zalasr", "HasStdExtZalasr", "true", - "'Zalasr' (Load-Acquire and Store-Release Instructions)">; + : RISCVExperimentalExtension<"zalasr", 0, 1, + "'Zalasr' (Load-Acquire and Store-Release Instructions)">; def HasStdExtZalasr : Predicate<"Subtarget->hasStdExtZalasr()">, AssemblerPredicate<(all_of FeatureStdExtZalasr), "'Zalasr' (Load-Acquire and Store-Release Instructions)">; def FeatureStdExtZalrsc - : SubtargetFeature<"experimental-zalrsc", "HasStdExtZalrsc", "true", - "'Zalrsc' (Load-Reserved/Store-Conditional)">; + : RISCVExperimentalExtension<"zalrsc", 0, 2, + "'Zalrsc' (Load-Reserved/Store-Conditional)">; def HasStdExtAOrZalrsc : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasStdExtZalrsc()">, AssemblerPredicate<(any_of FeatureStdExtA, FeatureStdExtZalrsc), @@ -211,11 +249,11 @@ def HasStdExtAOrZalrsc "'Zalrsc' (Load-Reserved/Store-Conditional)">; def FeatureStdExtZama16b - : SubtargetFeature<"zama16b", "HasStdExtZama16b", "true", - "'Zama16b' (Atomic 16-byte misaligned loads, stores and AMOs)">; + : RISCVExtension<"zama16b", 1, 0, + "'Zama16b' (Atomic 16-byte misaligned loads, stores and AMOs)">; -def FeatureStdExtZawrs : SubtargetFeature<"zawrs", "HasStdExtZawrs", "true", - "'Zawrs' (Wait on Reservation Set)">; +def FeatureStdExtZawrs : RISCVExtension<"zawrs", 1, 0, + "'Zawrs' (Wait on Reservation Set)">; def HasStdExtZawrs : Predicate<"Subtarget->hasStdExtZawrs()">, AssemblerPredicate<(all_of FeatureStdExtZawrs), "'Zawrs' (Wait on Reservation Set)">; @@ -223,43 +261,43 @@ def HasStdExtZawrs : Predicate<"Subtarget->hasStdExtZawrs()">, // Floating Point Extensions def FeatureStdExtF - : SubtargetFeature<"f", "HasStdExtF", "true", - "'F' (Single-Precision Floating-Point)", - [FeatureStdExtZicsr]>; + : RISCVExtension<"f", 2, 2, + "'F' (Single-Precision Floating-Point)", + [FeatureStdExtZicsr]>; def HasStdExtF : Predicate<"Subtarget->hasStdExtF()">, AssemblerPredicate<(all_of FeatureStdExtF), "'F' (Single-Precision Floating-Point)">; def FeatureStdExtD - : SubtargetFeature<"d", "HasStdExtD", "true", - "'D' (Double-Precision Floating-Point)", - [FeatureStdExtF]>; + : RISCVExtension<"d", 2, 2, + "'D' (Double-Precision Floating-Point)", + [FeatureStdExtF]>; def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">, AssemblerPredicate<(all_of FeatureStdExtD), "'D' (Double-Precision Floating-Point)">; def FeatureStdExtZfhmin - : SubtargetFeature<"zfhmin", "HasStdExtZfhmin", "true", - "'Zfhmin' (Half-Precision Floating-Point Minimal)", - [FeatureStdExtF]>; + : RISCVExtension<"zfhmin", 1, 0, + "'Zfhmin' (Half-Precision Floating-Point Minimal)", + [FeatureStdExtF]>; def HasStdExtZfhmin : Predicate<"Subtarget->hasStdExtZfhmin()">, AssemblerPredicate<(all_of FeatureStdExtZfhmin), "'Zfh' (Half-Precision Floating-Point) or " "'Zfhmin' (Half-Precision Floating-Point Minimal)">; def FeatureStdExtZfh - : SubtargetFeature<"zfh", "HasStdExtZfh", "true", - "'Zfh' (Half-Precision Floating-Point)", - [FeatureStdExtZfhmin]>; + : RISCVExtension<"zfh", 1, 0, + "'Zfh' (Half-Precision Floating-Point)", + [FeatureStdExtZfhmin]>; def HasStdExtZfh : Predicate<"Subtarget->hasStdExtZfh()">, AssemblerPredicate<(all_of FeatureStdExtZfh), "'Zfh' (Half-Precision Floating-Point)">; def NoStdExtZfh : Predicate<"!Subtarget->hasStdExtZfh()">; def FeatureStdExtZfbfmin - : SubtargetFeature<"experimental-zfbfmin", "HasStdExtZfbfmin", "true", - "'Zfbfmin' (Scalar BF16 Converts)", - [FeatureStdExtF]>; + : RISCVExperimentalExtension<"zfbfmin", 1, 0, + "'Zfbfmin' (Scalar BF16 Converts)", + [FeatureStdExtF]>; def HasStdExtZfbfmin : Predicate<"Subtarget->hasStdExtZfbfmin()">, AssemblerPredicate<(all_of FeatureStdExtZfbfmin), "'Zfbfmin' (Scalar BF16 Converts)">; @@ -273,42 +311,42 @@ def HasHalfFPLoadStoreMove "'Zfbfmin' (Scalar BF16 Converts)">; def FeatureStdExtZfa - : SubtargetFeature<"zfa", "HasStdExtZfa", "true", - "'Zfa' (Additional Floating-Point)", - [FeatureStdExtF]>; + : RISCVExtension<"zfa", 1, 0, + "'Zfa' (Additional Floating-Point)", + [FeatureStdExtF]>; def HasStdExtZfa : Predicate<"Subtarget->hasStdExtZfa()">, AssemblerPredicate<(all_of FeatureStdExtZfa), "'Zfa' (Additional Floating-Point)">; def FeatureStdExtZfinx - : SubtargetFeature<"zfinx", "HasStdExtZfinx", "true", - "'Zfinx' (Float in Integer)", - [FeatureStdExtZicsr]>; + : RISCVExtension<"zfinx", 1, 0, + "'Zfinx' (Float in Integer)", + [FeatureStdExtZicsr]>; def HasStdExtZfinx : Predicate<"Subtarget->hasStdExtZfinx()">, AssemblerPredicate<(all_of FeatureStdExtZfinx), "'Zfinx' (Float in Integer)">; def FeatureStdExtZdinx - : SubtargetFeature<"zdinx", "HasStdExtZdinx", "true", - "'Zdinx' (Double in Integer)", - [FeatureStdExtZfinx]>; + : RISCVExtension<"zdinx", 1, 0, + "'Zdinx' (Double in Integer)", + [FeatureStdExtZfinx]>; def HasStdExtZdinx : Predicate<"Subtarget->hasStdExtZdinx()">, AssemblerPredicate<(all_of FeatureStdExtZdinx), "'Zdinx' (Double in Integer)">; def FeatureStdExtZhinxmin - : SubtargetFeature<"zhinxmin", "HasStdExtZhinxmin", "true", - "'Zhinxmin' (Half Float in Integer Minimal)", - [FeatureStdExtZfinx]>; + : RISCVExtension<"zhinxmin", 1, 0, + "'Zhinxmin' (Half Float in Integer Minimal)", + [FeatureStdExtZfinx]>; def HasStdExtZhinxmin : Predicate<"Subtarget->hasStdExtZhinxmin()">, AssemblerPredicate<(all_of FeatureStdExtZhinxmin), "'Zhinx' (Half Float in Integer) or " "'Zhinxmin' (Half Float in Integer Minimal)">; def FeatureStdExtZhinx - : SubtargetFeature<"zhinx", "HasStdExtZhinx", "true", - "'Zhinx' (Half Float in Integer)", - [FeatureStdExtZhinxmin]>; + : RISCVExtension<"zhinx", 1, 0, + "'Zhinx' (Half Float in Integer)", + [FeatureStdExtZhinxmin]>; def HasStdExtZhinx : Predicate<"Subtarget->hasStdExtZhinx()">, AssemblerPredicate<(all_of FeatureStdExtZhinx), "'Zhinx' (Half Float in Integer)">; @@ -317,8 +355,8 @@ def NoStdExtZhinx : Predicate<"!Subtarget->hasStdExtZhinx()">; // Compressed Extensions def FeatureStdExtC - : SubtargetFeature<"c", "HasStdExtC", "true", - "'C' (Compressed Instructions)">; + : RISCVExtension<"c", 2, 0, + "'C' (Compressed Instructions)">; def HasStdExtC : Predicate<"Subtarget->hasStdExtC()">, AssemblerPredicate<(all_of FeatureStdExtC), "'C' (Compressed Instructions)">; @@ -331,9 +369,9 @@ def HasRVCHints : Predicate<"Subtarget->enableRVCHintInstrs()">, "RVC Hint Instructions">; def FeatureStdExtZca - : SubtargetFeature<"zca", "HasStdExtZca", "true", - "'Zca' (part of the C extension, excluding compressed " - "floating point loads/stores)">; + : RISCVExtension<"zca", 1, 0, + "'Zca' (part of the C extension, excluding compressed " + "floating point loads/stores)">; def HasStdExtCOrZca : Predicate<"Subtarget->hasStdExtCOrZca()">, @@ -343,17 +381,17 @@ def HasStdExtCOrZca "compressed floating point loads/stores)">; def FeatureStdExtZcb - : SubtargetFeature<"zcb", "HasStdExtZcb", "true", - "'Zcb' (Compressed basic bit manipulation instructions)", - [FeatureStdExtZca]>; + : RISCVExtension<"zcb", 1, 0, + "'Zcb' (Compressed basic bit manipulation instructions)", + [FeatureStdExtZca]>; def HasStdExtZcb : Predicate<"Subtarget->hasStdExtZcb()">, AssemblerPredicate<(all_of FeatureStdExtZcb), "'Zcb' (Compressed basic bit manipulation instructions)">; def FeatureStdExtZcd - : SubtargetFeature<"zcd", "HasStdExtZcd", "true", - "'Zcd' (Compressed Double-Precision Floating-Point Instructions)", - [FeatureStdExtZca]>; + : RISCVExtension<"zcd", 1, 0, + "'Zcd' (Compressed Double-Precision Floating-Point Instructions)", + [FeatureStdExtZca]>; def HasStdExtCOrZcd : Predicate<"Subtarget->hasStdExtCOrZcd()">, @@ -362,31 +400,31 @@ def HasStdExtCOrZcd "'Zcd' (Compressed Double-Precision Floating-Point Instructions)">; def FeatureStdExtZcf - : SubtargetFeature<"zcf", "HasStdExtZcf", "true", - "'Zcf' (Compressed Single-Precision Floating-Point Instructions)", - [FeatureStdExtZca]>; + : RISCVExtension<"zcf", 1, 0, + "'Zcf' (Compressed Single-Precision Floating-Point Instructions)", + [FeatureStdExtZca]>; def FeatureStdExtZcmp - : SubtargetFeature<"zcmp", "HasStdExtZcmp", "true", - "'Zcmp' (sequenced instuctions for code-size reduction)", - [FeatureStdExtZca]>; + : RISCVExtension<"zcmp", 1, 0, + "'Zcmp' (sequenced instuctions for code-size reduction)", + [FeatureStdExtZca]>; def HasStdExtZcmp : Predicate<"Subtarget->hasStdExtZcmp() && !Subtarget->hasStdExtC()">, AssemblerPredicate<(all_of FeatureStdExtZcmp), "'Zcmp' (sequenced instuctions for code-size reduction)">; def FeatureStdExtZcmt - : SubtargetFeature<"zcmt", "HasStdExtZcmt", "true", - "'Zcmt' (table jump instuctions for code-size reduction)", - [FeatureStdExtZca, FeatureStdExtZicsr]>; + : RISCVExtension<"zcmt", 1, 0, + "'Zcmt' (table jump instuctions for code-size reduction)", + [FeatureStdExtZca, FeatureStdExtZicsr]>; def HasStdExtZcmt : Predicate<"Subtarget->hasStdExtZcmt()">, AssemblerPredicate<(all_of FeatureStdExtZcmt), "'Zcmt' (table jump instuctions for code-size reduction)">; def FeatureStdExtZce - : SubtargetFeature<"zce", "HasStdExtZce", "true", - "'Zce' (Compressed extensions for microcontrollers)", - [FeatureStdExtZca, FeatureStdExtZcb, FeatureStdExtZcmp, - FeatureStdExtZcmt]>; + : RISCVExtension<"zce", 1, 0, + "'Zce' (Compressed extensions for microcontrollers)", + [FeatureStdExtZca, FeatureStdExtZcb, FeatureStdExtZcmp, + FeatureStdExtZcmt]>; def HasStdExtCOrZcfOrZce : Predicate<"Subtarget->hasStdExtC() || Subtarget->hasStdExtZcf() " @@ -396,9 +434,10 @@ def HasStdExtCOrZcfOrZce "'C' (Compressed Instructions) or " "'Zcf' (Compressed Single-Precision Floating-Point Instructions)">; -def FeatureStdExtZcmop : SubtargetFeature<"zcmop", "HasStdExtZcmop", "true", - "'Zcmop' (Compressed May-Be-Operations)", - [FeatureStdExtZca]>; +def FeatureStdExtZcmop + : RISCVExtension<"zcmop", 1, 0, + "'Zcmop' (Compressed May-Be-Operations)", + [FeatureStdExtZca]>; def HasStdExtZcmop : Predicate<"Subtarget->hasStdExtZcmop()">, AssemblerPredicate<(all_of FeatureStdExtZcmop), "'Zcmop' (Compressed May-Be-Operations)">; @@ -406,30 +445,30 @@ def HasStdExtZcmop : Predicate<"Subtarget->hasStdExtZcmop()">, // Bitmanip Extensions def FeatureStdExtZba - : SubtargetFeature<"zba", "HasStdExtZba", "true", - "'Zba' (Address Generation Instructions)">; + : RISCVExtension<"zba", 1, 0, + "'Zba' (Address Generation Instructions)">; def HasStdExtZba : Predicate<"Subtarget->hasStdExtZba()">, AssemblerPredicate<(all_of FeatureStdExtZba), "'Zba' (Address Generation Instructions)">; def NotHasStdExtZba : Predicate<"!Subtarget->hasStdExtZba()">; def FeatureStdExtZbb - : SubtargetFeature<"zbb", "HasStdExtZbb", "true", - "'Zbb' (Basic Bit-Manipulation)">; + : RISCVExtension<"zbb", 1, 0, + "'Zbb' (Basic Bit-Manipulation)">; def HasStdExtZbb : Predicate<"Subtarget->hasStdExtZbb()">, AssemblerPredicate<(all_of FeatureStdExtZbb), "'Zbb' (Basic Bit-Manipulation)">; def FeatureStdExtZbc - : SubtargetFeature<"zbc", "HasStdExtZbc", "true", - "'Zbc' (Carry-Less Multiplication)">; + : RISCVExtension<"zbc", 1, 0, + "'Zbc' (Carry-Less Multiplication)">; def HasStdExtZbc : Predicate<"Subtarget->hasStdExtZbc()">, AssemblerPredicate<(all_of FeatureStdExtZbc), "'Zbc' (Carry-Less Multiplication)">; def FeatureStdExtZbs - : SubtargetFeature<"zbs", "HasStdExtZbs", "true", - "'Zbs' (Single-Bit Instructions)">; + : RISCVExtension<"zbs", 1, 0, + "'Zbs' (Single-Bit Instructions)">; def HasStdExtZbs : Predicate<"Subtarget->hasStdExtZbs()">, AssemblerPredicate<(all_of FeatureStdExtZbs), "'Zbs' (Single-Bit Instructions)">; @@ -437,15 +476,15 @@ def HasStdExtZbs : Predicate<"Subtarget->hasStdExtZbs()">, // Bitmanip Extensions for Cryptography Extensions def FeatureStdExtZbkb - : SubtargetFeature<"zbkb", "HasStdExtZbkb", "true", - "'Zbkb' (Bitmanip instructions for Cryptography)">; + : RISCVExtension<"zbkb", 1, 0, + "'Zbkb' (Bitmanip instructions for Cryptography)">; def HasStdExtZbkb : Predicate<"Subtarget->hasStdExtZbkb()">, AssemblerPredicate<(all_of FeatureStdExtZbkb), "'Zbkb' (Bitmanip instructions for Cryptography)">; def FeatureStdExtZbkx - : SubtargetFeature<"zbkx", "HasStdExtZbkx", "true", - "'Zbkx' (Crossbar permutation instructions)">; + : RISCVExtension<"zbkx", 1, 0, + "'Zbkx' (Crossbar permutation instructions)">; def HasStdExtZbkx : Predicate<"Subtarget->hasStdExtZbkx()">, AssemblerPredicate<(all_of FeatureStdExtZbkx), "'Zbkx' (Crossbar permutation instructions)">; @@ -460,9 +499,9 @@ def HasStdExtZbbOrZbkb // carry-less multiply subextension. The former should be enabled if the latter // is enabled. def FeatureStdExtZbkc - : SubtargetFeature<"zbkc", "HasStdExtZbkc", "true", - "'Zbkc' (Carry-less multiply instructions for " - "Cryptography)">; + : RISCVExtension<"zbkc", 1, 0, + "'Zbkc' (Carry-less multiply instructions for " + "Cryptography)">; def HasStdExtZbkc : Predicate<"Subtarget->hasStdExtZbkc()">, AssemblerPredicate<(all_of FeatureStdExtZbkc), @@ -478,15 +517,15 @@ def HasStdExtZbcOrZbkc // Cryptography Extensions def FeatureStdExtZknd - : SubtargetFeature<"zknd", "HasStdExtZknd", "true", - "'Zknd' (NIST Suite: AES Decryption)">; + : RISCVExtension<"zknd", 1, 0, + "'Zknd' (NIST Suite: AES Decryption)">; def HasStdExtZknd : Predicate<"Subtarget->hasStdExtZknd()">, AssemblerPredicate<(all_of FeatureStdExtZknd), "'Zknd' (NIST Suite: AES Decryption)">; def FeatureStdExtZkne - : SubtargetFeature<"zkne", "HasStdExtZkne", "true", - "'Zkne' (NIST Suite: AES Encryption)">; + : RISCVExtension<"zkne", 1, 0, + "'Zkne' (NIST Suite: AES Encryption)">; def HasStdExtZkne : Predicate<"Subtarget->hasStdExtZkne()">, AssemblerPredicate<(all_of FeatureStdExtZkne), "'Zkne' (NIST Suite: AES Encryption)">; @@ -500,136 +539,138 @@ def HasStdExtZkndOrZkne "'Zkne' (NIST Suite: AES Encryption)">; def FeatureStdExtZknh - : SubtargetFeature<"zknh", "HasStdExtZknh", "true", - "'Zknh' (NIST Suite: Hash Function Instructions)">; + : RISCVExtension<"zknh", 1, 0, + "'Zknh' (NIST Suite: Hash Function Instructions)">; def HasStdExtZknh : Predicate<"Subtarget->hasStdExtZknh()">, AssemblerPredicate<(all_of FeatureStdExtZknh), "'Zknh' (NIST Suite: Hash Function Instructions)">; def FeatureStdExtZksed - : SubtargetFeature<"zksed", "HasStdExtZksed", "true", - "'Zksed' (ShangMi Suite: SM4 Block Cipher Instructions)">; + : RISCVExtension<"zksed", 1, 0, + "'Zksed' (ShangMi Suite: SM4 Block Cipher Instructions)">; def HasStdExtZksed : Predicate<"Subtarget->hasStdExtZksed()">, AssemblerPredicate<(all_of FeatureStdExtZksed), "'Zksed' (ShangMi Suite: SM4 Block Cipher Instructions)">; def FeatureStdExtZksh - : SubtargetFeature<"zksh", "HasStdExtZksh", "true", - "'Zksh' (ShangMi Suite: SM3 Hash Function Instructions)">; + : RISCVExtension<"zksh", 1, 0, + "'Zksh' (ShangMi Suite: SM3 Hash Function Instructions)">; def HasStdExtZksh : Predicate<"Subtarget->hasStdExtZksh()">, AssemblerPredicate<(all_of FeatureStdExtZksh), "'Zksh' (ShangMi Suite: SM3 Hash Function Instructions)">; def FeatureStdExtZkr - : SubtargetFeature<"zkr", "HasStdExtZkr", "true", - "'Zkr' (Entropy Source Extension)">; + : RISCVExtension<"zkr", 1, 0, + "'Zkr' (Entropy Source Extension)">; def HasStdExtZkr : Predicate<"Subtarget->hasStdExtZkr()">, AssemblerPredicate<(all_of FeatureStdExtZkr), "'Zkr' (Entropy Source Extension)">; def FeatureStdExtZkn - : SubtargetFeature<"zkn", "HasStdExtZkn", "true", - "'Zkn' (NIST Algorithm Suite)", - [FeatureStdExtZbkb, - FeatureStdExtZbkc, - FeatureStdExtZbkx, - FeatureStdExtZkne, - FeatureStdExtZknd, - FeatureStdExtZknh]>; + : RISCVExtension<"zkn", 1, 0, + "'Zkn' (NIST Algorithm Suite)", + [FeatureStdExtZbkb, + FeatureStdExtZbkc, + FeatureStdExtZbkx, + FeatureStdExtZkne, + FeatureStdExtZknd, + FeatureStdExtZknh]>; def FeatureStdExtZks - : SubtargetFeature<"zks", "HasStdExtZks", "true", - "'Zks' (ShangMi Algorithm Suite)", - [FeatureStdExtZbkb, - FeatureStdExtZbkc, - FeatureStdExtZbkx, - FeatureStdExtZksed, - FeatureStdExtZksh]>; + : RISCVExtension<"zks", 1, 0, + "'Zks' (ShangMi Algorithm Suite)", + [FeatureStdExtZbkb, + FeatureStdExtZbkc, + FeatureStdExtZbkx, + FeatureStdExtZksed, + FeatureStdExtZksh]>; def FeatureStdExtZkt - : SubtargetFeature<"zkt", "HasStdExtZkt", "true", - "'Zkt' (Data Independent Execution Latency)">; + : RISCVExtension<"zkt", 1, 0, + "'Zkt' (Data Independent Execution Latency)">; def FeatureStdExtZk - : SubtargetFeature<"zk", "HasStdExtZk", "true", - "'Zk' (Standard scalar cryptography extension)", - [FeatureStdExtZkn, - FeatureStdExtZkr, - FeatureStdExtZkt]>; + : RISCVExtension<"zk", 1, 0, + "'Zk' (Standard scalar cryptography extension)", + [FeatureStdExtZkn, + FeatureStdExtZkr, + FeatureStdExtZkt]>; // Vector Extensions -def FeatureStdExtZvl32b : SubtargetFeature<"zvl32b", "ZvlLen", "32", - "'Zvl' (Minimum Vector Length) 32">; +def FeatureStdExtZvl32b : RISCVExtension<"zvl32b", 1, 0, + "'Zvl' (Minimum Vector Length) 32", [], + "ZvlLen", "32">; foreach i = { 6-16 } in { defvar I = !shl(1, i); def FeatureStdExtZvl#I#b : - SubtargetFeature<"zvl"#I#"b", "ZvlLen", !cast(I), - "'Zvl' (Minimum Vector Length) "#I, - [!cast("FeatureStdExtZvl"#!srl(I, 1)#"b")]>; + RISCVExtension<"zvl"#I#"b", 1, 0, + "'Zvl' (Minimum Vector Length) "#I, + [!cast("FeatureStdExtZvl"#!srl(I, 1)#"b")], + "ZvlLen", !cast(I)>; } def FeatureStdExtZve32x - : SubtargetFeature<"zve32x", "HasStdExtZve32x", "true", - "'Zve32x' (Vector Extensions for Embedded Processors " - "with maximal 32 EEW)", - [FeatureStdExtZicsr, FeatureStdExtZvl32b]>; + : RISCVExtension<"zve32x", 1, 0, + "'Zve32x' (Vector Extensions for Embedded Processors " + "with maximal 32 EEW)", + [FeatureStdExtZicsr, FeatureStdExtZvl32b]>; def FeatureStdExtZve32f - : SubtargetFeature<"zve32f", "HasStdExtZve32f", "true", - "'Zve32f' (Vector Extensions for Embedded Processors " - "with maximal 32 EEW and F extension)", - [FeatureStdExtZve32x, FeatureStdExtF]>; + : RISCVExtension<"zve32f", 1, 0, + "'Zve32f' (Vector Extensions for Embedded Processors " + "with maximal 32 EEW and F extension)", + [FeatureStdExtZve32x, FeatureStdExtF]>; def FeatureStdExtZve64x - : SubtargetFeature<"zve64x", "HasStdExtZve64x", "true", - "'Zve64x' (Vector Extensions for Embedded Processors " - "with maximal 64 EEW)", - [FeatureStdExtZve32x, FeatureStdExtZvl64b]>; + : RISCVExtension<"zve64x", 1, 0, + "'Zve64x' (Vector Extensions for Embedded Processors " + "with maximal 64 EEW)", + [FeatureStdExtZve32x, FeatureStdExtZvl64b]>; def FeatureStdExtZve64f - : SubtargetFeature<"zve64f", "HasStdExtZve64f", "true", - "'Zve64f' (Vector Extensions for Embedded Processors " - "with maximal 64 EEW and F extension)", - [FeatureStdExtZve32f, FeatureStdExtZve64x]>; + : RISCVExtension<"zve64f", 1, 0, + "'Zve64f' (Vector Extensions for Embedded Processors " + "with maximal 64 EEW and F extension)", + [FeatureStdExtZve32f, FeatureStdExtZve64x]>; def FeatureStdExtZve64d - : SubtargetFeature<"zve64d", "HasStdExtZve64d", "true", - "'Zve64d' (Vector Extensions for Embedded Processors " - "with maximal 64 EEW, F and D extension)", - [FeatureStdExtZve64f, FeatureStdExtD]>; + : RISCVExtension<"zve64d", 1, 0, + "'Zve64d' (Vector Extensions for Embedded Processors " + "with maximal 64 EEW, F and D extension)", + [FeatureStdExtZve64f, FeatureStdExtD]>; def FeatureStdExtV - : SubtargetFeature<"v", "HasStdExtV", "true", - "'V' (Vector Extension for Application Processors)", - [FeatureStdExtZvl128b, FeatureStdExtZve64d]>; + : RISCVExtension<"v", 1, 0, + "'V' (Vector Extension for Application Processors)", + [FeatureStdExtZvl128b, FeatureStdExtZve64d]>; def FeatureStdExtZvfbfmin - : SubtargetFeature<"experimental-zvfbfmin", "HasStdExtZvfbfmin", "true", - "'Zvbfmin' (Vector BF16 Converts)", - [FeatureStdExtZve32f]>; + : RISCVExperimentalExtension<"zvfbfmin", 1, 0, + "'Zvbfmin' (Vector BF16 Converts)", + [FeatureStdExtZve32f]>; def HasStdExtZvfbfmin : Predicate<"Subtarget->hasStdExtZvfbfmin()">, AssemblerPredicate<(all_of FeatureStdExtZvfbfmin), "'Zvfbfmin' (Vector BF16 Converts)">; def FeatureStdExtZvfbfwma - : SubtargetFeature<"experimental-zvfbfwma", "HasStdExtZvfbfwma", "true", - "'Zvfbfwma' (Vector BF16 widening mul-add)", - [FeatureStdExtZvfbfmin, FeatureStdExtZfbfmin]>; + : RISCVExperimentalExtension<"zvfbfwma", 1, 0, + "'Zvfbfwma' (Vector BF16 widening mul-add)", + [FeatureStdExtZvfbfmin, FeatureStdExtZfbfmin]>; def HasStdExtZvfbfwma : Predicate<"Subtarget->hasStdExtZvfbfwma()">, AssemblerPredicate<(all_of FeatureStdExtZvfbfwma), "'Zvfbfwma' (Vector BF16 widening mul-add)">; def FeatureStdExtZvfhmin - : SubtargetFeature<"zvfhmin", "HasStdExtZvfhmin", "true", - "'Zvfhmin' (Vector Half-Precision Floating-Point Minimal)", - [FeatureStdExtZve32f]>; + : RISCVExtension<"zvfhmin", 1, 0, + "'Zvfhmin' (Vector Half-Precision Floating-Point Minimal)", + [FeatureStdExtZve32f]>; def FeatureStdExtZvfh - : SubtargetFeature<"zvfh", "HasStdExtZvfh", "true", - "'Zvfh' (Vector Half-Precision Floating-Point)", - [FeatureStdExtZvfhmin, FeatureStdExtZfhmin]>; + : RISCVExtension<"zvfh", 1, 0, + "'Zvfh' (Vector Half-Precision Floating-Point)", + [FeatureStdExtZvfhmin, FeatureStdExtZfhmin]>; def HasStdExtZfhOrZvfh : Predicate<"Subtarget->hasStdExtZfh() || Subtarget->hasStdExtZvfh()">, @@ -640,52 +681,52 @@ def HasStdExtZfhOrZvfh // Vector Cryptography and Bitmanip Extensions def FeatureStdExtZvkb - : SubtargetFeature<"zvkb", "HasStdExtZvkb", "true", - "'Zvkb' (Vector Bit-manipulation used in Cryptography)">; + : RISCVExtension<"zvkb", 1, 0, + "'Zvkb' (Vector Bit-manipulation used in Cryptography)">; def HasStdExtZvkb : Predicate<"Subtarget->hasStdExtZvkb()">, AssemblerPredicate<(all_of FeatureStdExtZvkb), "'Zvkb' (Vector Bit-manipulation used in Cryptography)">; def FeatureStdExtZvbb - : SubtargetFeature<"zvbb", "HasStdExtZvbb", "true", - "'Zvbb' (Vector basic bit-manipulation instructions)", - [FeatureStdExtZvkb]>; + : RISCVExtension<"zvbb", 1, 0, + "'Zvbb' (Vector basic bit-manipulation instructions)", + [FeatureStdExtZvkb]>; def HasStdExtZvbb : Predicate<"Subtarget->hasStdExtZvbb()">, AssemblerPredicate<(all_of FeatureStdExtZvbb), "'Zvbb' (Vector basic bit-manipulation instructions)">; def FeatureStdExtZvbc - : SubtargetFeature<"zvbc", "HasStdExtZvbc", "true", - "'Zvbc' (Vector Carryless Multiplication)">; + : RISCVExtension<"zvbc", 1, 0, + "'Zvbc' (Vector Carryless Multiplication)">; def HasStdExtZvbc : Predicate<"Subtarget->hasStdExtZvbc()">, AssemblerPredicate<(all_of FeatureStdExtZvbc), "'Zvbc' (Vector Carryless Multiplication)">; def FeatureStdExtZvkg - : SubtargetFeature<"zvkg", "HasStdExtZvkg", "true", - "'Zvkg' (Vector GCM instructions for Cryptography)">; + : RISCVExtension<"zvkg", 1, 0, + "'Zvkg' (Vector GCM instructions for Cryptography)">; def HasStdExtZvkg : Predicate<"Subtarget->hasStdExtZvkg()">, AssemblerPredicate<(all_of FeatureStdExtZvkg), "'Zvkg' (Vector GCM instructions for Cryptography)">; def FeatureStdExtZvkned - : SubtargetFeature<"zvkned", "HasStdExtZvkned", "true", - "'Zvkned' (Vector AES Encryption & Decryption (Single Round))">; + : RISCVExtension<"zvkned", 1, 0, + "'Zvkned' (Vector AES Encryption & Decryption (Single Round))">; def HasStdExtZvkned : Predicate<"Subtarget->hasStdExtZvkned()">, AssemblerPredicate<(all_of FeatureStdExtZvkned), "'Zvkned' (Vector AES Encryption & Decryption (Single Round))">; def FeatureStdExtZvknha - : SubtargetFeature<"zvknha", "HasStdExtZvknha", "true", - "'Zvknha' (Vector SHA-2 (SHA-256 only))">; + : RISCVExtension<"zvknha", 1, 0, + "'Zvknha' (Vector SHA-2 (SHA-256 only))">; def HasStdExtZvknha : Predicate<"Subtarget->hasStdExtZvknha()">, AssemblerPredicate<(all_of FeatureStdExtZvknha), "'Zvknha' (Vector SHA-2 (SHA-256 only))">; def FeatureStdExtZvknhb - : SubtargetFeature<"zvknhb", "HasStdExtZvknhb", "true", - "'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512))", - [FeatureStdExtZve64x]>; + : RISCVExtension<"zvknhb", 1, 0, + "'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512))", + [FeatureStdExtZve64x]>; def HasStdExtZvknhb : Predicate<"Subtarget->hasStdExtZvknhb()">, AssemblerPredicate<(all_of FeatureStdExtZvknhb), "'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512))">; @@ -695,58 +736,58 @@ def HasStdExtZvknhaOrZvknhb : Predicate<"Subtarget->hasStdExtZvknha() || Subtarg "'Zvknha' or 'Zvknhb' (Vector SHA-2)">; def FeatureStdExtZvksed - : SubtargetFeature<"zvksed", "HasStdExtZvksed", "true", - "'Zvksed' (SM4 Block Cipher Instructions)">; + : RISCVExtension<"zvksed", 1, 0, + "'Zvksed' (SM4 Block Cipher Instructions)">; def HasStdExtZvksed : Predicate<"Subtarget->hasStdExtZvksed()">, AssemblerPredicate<(all_of FeatureStdExtZvksed), "'Zvksed' (SM4 Block Cipher Instructions)">; def FeatureStdExtZvksh - : SubtargetFeature<"zvksh", "HasStdExtZvksh", "true", - "'Zvksh' (SM3 Hash Function Instructions)">; + : RISCVExtension<"zvksh", 1, 0, + "'Zvksh' (SM3 Hash Function Instructions)">; def HasStdExtZvksh : Predicate<"Subtarget->hasStdExtZvksh()">, AssemblerPredicate<(all_of FeatureStdExtZvksh), "'Zvksh' (SM3 Hash Function Instructions)">; def FeatureStdExtZvkt - : SubtargetFeature<"zvkt", "HasStdExtZvkt", "true", - "'Zvkt' (Vector Data-Independent Execution Latency)">; + : RISCVExtension<"zvkt", 1, 0, + "'Zvkt' (Vector Data-Independent Execution Latency)">; // Zvk short-hand extensions def FeatureStdExtZvkn - : SubtargetFeature<"zvkn", "HasStdExtZvkn", "true", - "'Zvkn' (shorthand for 'Zvkned', 'Zvknhb', 'Zvkb', and " - "'Zvkt')", - [FeatureStdExtZvkned, FeatureStdExtZvknhb, - FeatureStdExtZvkb, FeatureStdExtZvkt]>; + : RISCVExtension<"zvkn", 1, 0, + "'Zvkn' (shorthand for 'Zvkned', 'Zvknhb', 'Zvkb', and " + "'Zvkt')", + [FeatureStdExtZvkned, FeatureStdExtZvknhb, + FeatureStdExtZvkb, FeatureStdExtZvkt]>; def FeatureStdExtZvknc - : SubtargetFeature<"zvknc", "HasStdExtZvknc", "true", - "'Zvknc' (shorthand for 'Zvknc' and 'Zvbc')", - [FeatureStdExtZvkn, FeatureStdExtZvbc]>; + : RISCVExtension<"zvknc", 1, 0, + "'Zvknc' (shorthand for 'Zvknc' and 'Zvbc')", + [FeatureStdExtZvkn, FeatureStdExtZvbc]>; def FeatureStdExtZvkng - : SubtargetFeature<"zvkng", "HasStdExtZvkng", "true", - "'zvkng' (shorthand for 'Zvkn' and 'Zvkg')", - [FeatureStdExtZvkn, FeatureStdExtZvkg]>; + : RISCVExtension<"zvkng", 1, 0, + "'zvkng' (shorthand for 'Zvkn' and 'Zvkg')", + [FeatureStdExtZvkn, FeatureStdExtZvkg]>; def FeatureStdExtZvks - : SubtargetFeature<"zvks", "HasStdExtZvks", "true", - "'Zvks' (shorthand for 'Zvksed', 'Zvksh', 'Zvkb', and " - "'Zvkt')", - [FeatureStdExtZvksed, FeatureStdExtZvksh, - FeatureStdExtZvkb, FeatureStdExtZvkt]>; + : RISCVExtension<"zvks", 1, 0, + "'Zvks' (shorthand for 'Zvksed', 'Zvksh', 'Zvkb', and " + "'Zvkt')", + [FeatureStdExtZvksed, FeatureStdExtZvksh, + FeatureStdExtZvkb, FeatureStdExtZvkt]>; def FeatureStdExtZvksc - : SubtargetFeature<"zvksc", "HasStdExtZvksc", "true", - "'Zvksc' (shorthand for 'Zvks' and 'Zvbc')", - [FeatureStdExtZvks, FeatureStdExtZvbc]>; + : RISCVExtension<"zvksc", 1, 0, + "'Zvksc' (shorthand for 'Zvks' and 'Zvbc')", + [FeatureStdExtZvks, FeatureStdExtZvbc]>; def FeatureStdExtZvksg - : SubtargetFeature<"zvksg", "HasStdExtZvksg", "true", - "'Zvksg' (shorthand for 'Zvks' and 'Zvkg')", - [FeatureStdExtZvks, FeatureStdExtZvkg]>; + : RISCVExtension<"zvksg", 1, 0, + "'Zvksg' (shorthand for 'Zvks' and 'Zvkg')", + [FeatureStdExtZvks, FeatureStdExtZvkg]>; // Vector instruction predicates @@ -780,8 +821,8 @@ def HasVInstructionsFullMultiply : Predicate<"Subtarget->hasVInstructionsFullMul // Hypervisor Extensions def FeatureStdExtH - : SubtargetFeature<"h", "HasStdExtH", "true", - "'H' (Hypervisor)">; + : RISCVExtension<"h", 1, 0, + "'H' (Hypervisor)">; def HasStdExtH : Predicate<"Subtarget->hasStdExtH()">, AssemblerPredicate<(all_of FeatureStdExtH), @@ -790,105 +831,104 @@ def HasStdExtH : Predicate<"Subtarget->hasStdExtH()">, // Supervisor extensions def FeatureStdExtShgatpa - : SubtargetFeature<"shgatpa", "HasStdExtShgatpa", "true", - "'Sgatpa' (SvNNx4 mode supported for all modes supported by satp, as well as Bare)", []>; + : RISCVExtension<"shgatpa", 1, 0, + "'Sgatpa' (SvNNx4 mode supported for all modes supported by satp, as well as Bare)">; def FeatureStdExtShvsatpa - : SubtargetFeature<"shvsatpa", "HasStdExtSvsatpa", "true", - "'Svsatpa' (vsatp supports all modes supported by satp)", []>; + : RISCVExtension<"shvsatpa", 1, 0, + "'Svsatpa' (vsatp supports all modes supported by satp)">; def FeatureStdExtSmaia - : SubtargetFeature<"smaia", "HasStdExtSmaia", "true", - "'Smaia' (Advanced Interrupt Architecture Machine " - "Level)", []>; + : RISCVExtension<"smaia", 1, 0, + "'Smaia' (Advanced Interrupt Architecture Machine Level)">; def FeatureStdExtSsaia - : SubtargetFeature<"ssaia", "HasStdExtSsaia", "true", - "'Ssaia' (Advanced Interrupt Architecture Supervisor " - "Level)", []>; + : RISCVExtension<"ssaia", 1, 0, + "'Ssaia' (Advanced Interrupt Architecture Supervisor " + "Level)">; def FeatureStdExtSmepmp - : SubtargetFeature<"smepmp", "HasStdExtSmepmp", "true", - "'Smepmp' (Enhanced Physical Memory Protection)", []>; + : RISCVExtension<"smepmp", 1, 0, + "'Smepmp' (Enhanced Physical Memory Protection)">; def FeatureStdExtSsccptr - : SubtargetFeature<"ssccptr", "HasStdExtSsccptr", "true", - "'Ssccptr' (Main memory supports page table reads)", []>; + : RISCVExtension<"ssccptr", 1, 0, + "'Ssccptr' (Main memory supports page table reads)">; def FeatureStdExtSscofpmf - : SubtargetFeature<"sscofpmf", "HasStdExtSscofpmf", "true", - "'Sscofpmf' (Count Overflow and Mode-Based Filtering)", []>; + : RISCVExtension<"sscofpmf", 1, 0, + "'Sscofpmf' (Count Overflow and Mode-Based Filtering)">; def FeatureStdExtShcounterenw - : SubtargetFeature<"shcounterenw", "HasStdExtShcounterenw", "true", - "'Shcounterenw' (Support writeable hcounteren enable " - "bit for any hpmcounter that is not read-only zero)", []>; + : RISCVExtension<"shcounterenw", 1, 0, + "'Shcounterenw' (Support writeable hcounteren enable " + "bit for any hpmcounter that is not read-only zero)">; def FeatureStdExtSscounterenw - : SubtargetFeature<"sscounterenw", "HasStdExtSscounterenw", "true", - "'Sscounterenw' (Support writeable scounteren enable " - "bit for any hpmcounter that is not read-only zero)", []>; + : RISCVExtension<"sscounterenw", 1, 0, + "'Sscounterenw' (Support writeable scounteren enable " + "bit for any hpmcounter that is not read-only zero)">; def FeatureStdExtSsstateen - : SubtargetFeature<"ssstateen", "HasStdExtSsstateen", "true", - "'Ssstateen' (Supervisor-mode view of the state-enable extension)", []>; + : RISCVExtension<"ssstateen", 1, 0, + "'Ssstateen' (Supervisor-mode view of the state-enable extension)">; def FeatureStdExtSsstrict - : SubtargetFeature<"ssstrict", "HasStdExtSsstrict", "true", - "'Ssstrict' (No non-conforming extensions are present)", []>; + : RISCVExtension<"ssstrict", 1, 0, + "'Ssstrict' (No non-conforming extensions are present)">; def FeatureStdExtSstc - : SubtargetFeature<"sstc", "HasStdExtSstc", "true", - "'Sstc' (Supervisor-mode timer interrupts)", []>; + : RISCVExtension<"sstc", 1, 0, + "'Sstc' (Supervisor-mode timer interrupts)">; def FeaturesSsqosid - : SubtargetFeature<"experimental-ssqosid", "HasStdExtSsqosid", "true", - "'Ssqosid' (Quality-of-Service (QoS) Identifiers)", []>; + : RISCVExperimentalExtension<"ssqosid", 1, 0, + "'Ssqosid' (Quality-of-Service (QoS) Identifiers)">; def FeatureStdExtShtvala - : SubtargetFeature<"shtvala", "HasStdExtShtvala", "true", - "'Shtvala' (htval provides all needed values)", []>; + : RISCVExtension<"shtvala", 1, 0, + "'Shtvala' (htval provides all needed values)">; def FeatureStdExtShvstvala - : SubtargetFeature<"shvstvala", "HasStdExtShvstvala", "true", - "'Shvstvala' (vstval provides all needed values)", []>; + : RISCVExtension<"shvstvala", 1, 0, + "'Shvstvala' (vstval provides all needed values)">; def FeatureStdExtSstvala - : SubtargetFeature<"sstvala", "HasStdExtSstvala", "true", - "'Sstvala' (stval provides all needed values)", []>; + : RISCVExtension<"sstvala", 1, 0, + "'Sstvala' (stval provides all needed values)">; def FeatureStdExtShvstvecd - : SubtargetFeature<"shvstvecd", "HasStdExtShvstvecd", "true", - "'Shvstvecd' (vstvec supports Direct mode)", []>; + : RISCVExtension<"shvstvecd", 1, 0, + "'Shvstvecd' (vstvec supports Direct mode)">; def FeatureStdExtSstvecd - : SubtargetFeature<"sstvecd", "HasStdExtSstvecd", "true", - "'Sstvecd' (stvec supports Direct mode)", []>; + : RISCVExtension<"sstvecd", 1, 0, + "'Sstvecd' (stvec supports Direct mode)">; def FeatureStdExtSsu64xl - : SubtargetFeature<"ssu64xl", "HasStdExtSsu64xl", "true", - "'Ssu64xl' (UXLEN=64 supported)", []>; + : RISCVExtension<"ssu64xl", 1, 0, + "'Ssu64xl' (UXLEN=64 supported)">; def FeatureStdExtSvade - : SubtargetFeature<"svade", "HasStdExtSvade", "true", - "'Svade' (Raise exceptions on improper A/D bits)", []>; + : RISCVExtension<"svade", 1, 0, + "'Svade' (Raise exceptions on improper A/D bits)">; def FeatureStdExtSvadu - : SubtargetFeature<"svadu", "HasStdExtSvadu", "true", - "'Svadu' (Hardware A/D updates)", []>; + : RISCVExtension<"svadu", 1, 0, + "'Svadu' (Hardware A/D updates)">; def FeatureStdExtSvbare - : SubtargetFeature<"svbare", "HasStdExtSvbare", "true", - "'Svbare' $(satp mode Bare supported)", []>; + : RISCVExtension<"svbare", 1, 0, + "'Svbare' $(satp mode Bare supported)">; def FeatureStdExtSvinval - : SubtargetFeature<"svinval", "HasStdExtSvinval", "true", - "'Svinval' (Fine-Grained Address-Translation Cache Invalidation)">; + : RISCVExtension<"svinval", 1, 0, + "'Svinval' (Fine-Grained Address-Translation Cache Invalidation)">; def HasStdExtSvinval : Predicate<"Subtarget->hasStdExtSvinval()">, AssemblerPredicate<(all_of FeatureStdExtSvinval), "'Svinval' (Fine-Grained Address-Translation Cache Invalidation)">; def FeatureStdExtSvnapot - : SubtargetFeature<"svnapot", "HasStdExtSvnapot", "true", - "'Svnapot' (NAPOT Translation Contiguity)">; + : RISCVExtension<"svnapot", 1, 0, + "'Svnapot' (NAPOT Translation Contiguity)">; def FeatureStdExtSvpbmt - : SubtargetFeature<"svpbmt", "HasStdExtSvpbmt", "true", - "'Svpbmt' (Page-Based Memory Types)">; + : RISCVExtension<"svpbmt", 1, 0, + "'Svpbmt' (Page-Based Memory Types)">; // Pointer Masking extensions @@ -896,33 +936,33 @@ def FeatureStdExtSvpbmt // privilege mode (U-mode), and for VS- and VU-modes if the H extension is // present. def FeatureStdExtSsnpm - : SubtargetFeature<"experimental-ssnpm", "HasStdExtSsnpm", "true", - "'Ssnpm' (Supervisor-level Pointer Masking for next lower privilege mode)">; + : RISCVExperimentalExtension<"ssnpm", 0, 8, + "'Ssnpm' (Supervisor-level Pointer Masking for next lower privilege mode)">; // A machine-level extension that provides pointer masking for the next lower // privilege mode (S/HS if S-mode is implemented, or U-mode otherwise). def FeatureStdExtSmnpm - : SubtargetFeature<"experimental-smnpm", "HasStdExtSmnpm", "true", - "'Smnpm' (Machine-level Pointer Masking for next lower privilege mode)">; + : RISCVExperimentalExtension<"smnpm", 0, 8, + "'Smnpm' (Machine-level Pointer Masking for next lower privilege mode)">; // A machine-level extension that provides pointer masking for M-mode. def FeatureStdExtSmmpm - : SubtargetFeature<"experimental-smmpm", "HasStdExtSmmpm", "true", - "'Smmpm' (Machine-level Pointer Masking for M-mode)">; + : RISCVExperimentalExtension<"smmpm", 0, 8, + "'Smmpm' (Machine-level Pointer Masking for M-mode)">; // An extension that indicates that there is pointer-masking support available // in supervisor mode, with some facility provided in the supervisor execution // environment to control pointer masking. def FeatureStdExtSspm - : SubtargetFeature<"experimental-sspm", "HasStdExtSspm", "true", - "'Sspm' (Indicates Supervisor-mode Pointer Masking)">; + : RISCVExperimentalExtension<"sspm", 0, 8, + "'Sspm' (Indicates Supervisor-mode Pointer Masking)">; // An extension that indicates that there is pointer-masking support available // in user mode, with some facility provided in the application execution // environment to control pointer masking. def FeatureStdExtSupm - : SubtargetFeature<"experimental-supm", "HasStdExtSupm", "true", - "'Supm' (Indicates User-mode Pointer Masking)">; + : RISCVExperimentalExtension<"supm", 0, 8, + "'Supm' (Indicates User-mode Pointer Masking)">; //===----------------------------------------------------------------------===// // Vendor extensions @@ -931,8 +971,8 @@ def FeatureStdExtSupm // Ventana Extenions def FeatureVendorXVentanaCondOps - : SubtargetFeature<"xventanacondops", "HasVendorXVentanaCondOps", "true", - "'XVentanaCondOps' (Ventana Conditional Ops)">; + : RISCVExtension<"xventanacondops", 1, 0, + "'XVentanaCondOps' (Ventana Conditional Ops)">; def HasVendorXVentanaCondOps : Predicate<"Subtarget->hasVendorXVentanaCondOps()">, AssemblerPredicate<(all_of FeatureVendorXVentanaCondOps), "'XVentanaCondOps' (Ventana Conditional Ops)">; @@ -940,80 +980,80 @@ def HasVendorXVentanaCondOps : Predicate<"Subtarget->hasVendorXVentanaCondOps()" // T-Head Extensions def FeatureVendorXTHeadBa - : SubtargetFeature<"xtheadba", "HasVendorXTHeadBa", "true", - "'xtheadba' (T-Head address calculation instructions)">; + : RISCVExtension<"xtheadba", 1, 0, + "'xtheadba' (T-Head address calculation instructions)">; def HasVendorXTHeadBa : Predicate<"Subtarget->hasVendorXTHeadBa()">, AssemblerPredicate<(all_of FeatureVendorXTHeadBa), "'xtheadba' (T-Head address calculation instructions)">; def FeatureVendorXTHeadBb - : SubtargetFeature<"xtheadbb", "HasVendorXTHeadBb", "true", - "'xtheadbb' (T-Head basic bit-manipulation instructions)">; + : RISCVExtension<"xtheadbb", 1, 0, + "'xtheadbb' (T-Head basic bit-manipulation instructions)">; def HasVendorXTHeadBb : Predicate<"Subtarget->hasVendorXTHeadBb()">, AssemblerPredicate<(all_of FeatureVendorXTHeadBb), "'xtheadbb' (T-Head basic bit-manipulation instructions)">; def FeatureVendorXTHeadBs - : SubtargetFeature<"xtheadbs", "HasVendorXTHeadBs", "true", - "'xtheadbs' (T-Head single-bit instructions)">; + : RISCVExtension<"xtheadbs", 1, 0, + "'xtheadbs' (T-Head single-bit instructions)">; def HasVendorXTHeadBs : Predicate<"Subtarget->hasVendorXTHeadBs()">, AssemblerPredicate<(all_of FeatureVendorXTHeadBs), "'xtheadbs' (T-Head single-bit instructions)">; def FeatureVendorXTHeadCondMov - : SubtargetFeature<"xtheadcondmov", "HasVendorXTHeadCondMov", "true", - "'xtheadcondmov' (T-Head conditional move instructions)">; + : RISCVExtension<"xtheadcondmov", 1, 0, + "'xtheadcondmov' (T-Head conditional move instructions)">; def HasVendorXTHeadCondMov : Predicate<"Subtarget->hasVendorXTHeadCondMov()">, AssemblerPredicate<(all_of FeatureVendorXTHeadCondMov), "'xtheadcondmov' (T-Head conditional move instructions)">; def FeatureVendorXTHeadCmo - : SubtargetFeature<"xtheadcmo", "HasVendorXTHeadCmo", "true", - "'xtheadcmo' (T-Head cache management instructions)">; + : RISCVExtension<"xtheadcmo", 1, 0, + "'xtheadcmo' (T-Head cache management instructions)">; def HasVendorXTHeadCmo : Predicate<"Subtarget->hasVendorXTHeadCmo()">, AssemblerPredicate<(all_of FeatureVendorXTHeadCmo), "'xtheadcmo' (T-Head cache management instructions)">; def FeatureVendorXTHeadFMemIdx - : SubtargetFeature<"xtheadfmemidx", "HasVendorXTHeadFMemIdx", "true", - "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)", - [FeatureStdExtF]>; + : RISCVExtension<"xtheadfmemidx", 1, 0, + "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)", + [FeatureStdExtF]>; def HasVendorXTHeadFMemIdx : Predicate<"Subtarget->hasVendorXTHeadFMemIdx()">, AssemblerPredicate<(all_of FeatureVendorXTHeadFMemIdx), "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)">; def FeatureVendorXTHeadMac - : SubtargetFeature<"xtheadmac", "HasVendorXTHeadMac", "true", - "'xtheadmac' (T-Head Multiply-Accumulate Instructions)">; + : RISCVExtension<"xtheadmac", 1, 0, + "'xtheadmac' (T-Head Multiply-Accumulate Instructions)">; def HasVendorXTHeadMac : Predicate<"Subtarget->hasVendorXTHeadMac()">, AssemblerPredicate<(all_of FeatureVendorXTHeadMac), "'xtheadmac' (T-Head Multiply-Accumulate Instructions)">; def FeatureVendorXTHeadMemIdx - : SubtargetFeature<"xtheadmemidx", "HasVendorXTHeadMemIdx", "true", - "'xtheadmemidx' (T-Head Indexed Memory Operations)">; + : RISCVExtension<"xtheadmemidx", 1, 0, + "'xtheadmemidx' (T-Head Indexed Memory Operations)">; def HasVendorXTHeadMemIdx : Predicate<"Subtarget->hasVendorXTHeadMemIdx()">, AssemblerPredicate<(all_of FeatureVendorXTHeadMemIdx), "'xtheadmemidx' (T-Head Indexed Memory Operations)">; def FeatureVendorXTHeadMemPair - : SubtargetFeature<"xtheadmempair", "HasVendorXTHeadMemPair", "true", - "'xtheadmempair' (T-Head two-GPR Memory Operations)">; + : RISCVExtension<"xtheadmempair", 1, 0, + "'xtheadmempair' (T-Head two-GPR Memory Operations)">; def HasVendorXTHeadMemPair : Predicate<"Subtarget->hasVendorXTHeadMemPair()">, AssemblerPredicate<(all_of FeatureVendorXTHeadMemPair), "'xtheadmempair' (T-Head two-GPR Memory Operations)">; def FeatureVendorXTHeadSync - : SubtargetFeature<"xtheadsync", "HasVendorXTHeadSync", "true", - "'xtheadsync' (T-Head multicore synchronization instructions)">; + : RISCVExtension<"xtheadsync", 1, 0, + "'xtheadsync' (T-Head multicore synchronization instructions)">; def HasVendorXTHeadSync : Predicate<"Subtarget->hasVendorXTHeadSync()">, AssemblerPredicate<(all_of FeatureVendorXTHeadSync), "'xtheadsync' (T-Head multicore synchronization instructions)">; def FeatureVendorXTHeadVdot - : SubtargetFeature<"xtheadvdot", "HasVendorXTHeadVdot", "true", - "'xtheadvdot' (T-Head Vector Extensions for Dot)", - [FeatureStdExtV]>; + : RISCVExtension<"xtheadvdot", 1, 0, + "'xtheadvdot' (T-Head Vector Extensions for Dot)", + [FeatureStdExtV]>; def HasVendorXTHeadVdot : Predicate<"Subtarget->hasVendorXTHeadVdot()">, AssemblerPredicate<(all_of FeatureVendorXTHeadVdot), "'xtheadvdot' (T-Head Vector Extensions for Dot)">; @@ -1021,68 +1061,68 @@ def HasVendorXTHeadVdot : Predicate<"Subtarget->hasVendorXTHeadVdot()">, // SiFive Extensions def FeatureVendorXSfvcp - : SubtargetFeature<"xsfvcp", "HasVendorXSfvcp", "true", - "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)", - [FeatureStdExtZve32x]>; + : RISCVExtension<"xsfvcp", 1, 0, + "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)", + [FeatureStdExtZve32x]>; def HasVendorXSfvcp : Predicate<"Subtarget->hasVendorXSfvcp()">, AssemblerPredicate<(all_of FeatureVendorXSfvcp), "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)">; def FeatureVendorXSfvqmaccdod - : SubtargetFeature<"xsfvqmaccdod", "HasVendorXSfvqmaccdod", "true", - "'XSfvqmaccdod' (SiFive Int8 Matrix Multiplication Instructions (2-by-8 and 8-by-2))", - [FeatureStdExtZve32x]>; + : RISCVExtension<"xsfvqmaccdod", 1, 0, + "'XSfvqmaccdod' (SiFive Int8 Matrix Multiplication Instructions (2-by-8 and 8-by-2))", + [FeatureStdExtZve32x]>; def HasVendorXSfvqmaccdod : Predicate<"Subtarget->hasVendorXSfvqmaccdod()">, AssemblerPredicate<(all_of FeatureVendorXSfvqmaccdod), "'XSfvqmaccdod' (SiFive Int8 Matrix Multiplication Instructions (2-by-8 and 8-by-2))">; def FeatureVendorXSfvqmaccqoq - : SubtargetFeature<"xsfvqmaccqoq", "HasVendorXSfvqmaccqoq", "true", - "'XSfvqmaccqoq' (SiFive Int8 Matrix Multiplication Instructions (4-by-8 and 8-by-4))", - [FeatureStdExtZve32x]>; + : RISCVExtension<"xsfvqmaccqoq", 1, 0, + "'XSfvqmaccqoq' (SiFive Int8 Matrix Multiplication Instructions (4-by-8 and 8-by-4))", + [FeatureStdExtZve32x]>; def HasVendorXSfvqmaccqoq : Predicate<"Subtarget->hasVendorXSfvqmaccqoq()">, AssemblerPredicate<(all_of FeatureVendorXSfvqmaccqoq), "'XSfvqmaccqoq' (SiFive Int8 Matrix Multiplication Instructions (4-by-8 and 8-by-4))">; def FeatureVendorXSfvfwmaccqqq - : SubtargetFeature<"xsfvfwmaccqqq", "HasVendorXSfvfwmaccqqq", "true", - "'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))", - [FeatureStdExtZve32f, FeatureStdExtZvfbfmin]>; + : RISCVExtension<"xsfvfwmaccqqq", 1, 0, + "'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))", + [FeatureStdExtZve32f, FeatureStdExtZvfbfmin]>; def HasVendorXSfvfwmaccqqq : Predicate<"Subtarget->hasVendorXSfvfwmaccqqq()">, AssemblerPredicate<(all_of FeatureVendorXSfvfwmaccqqq), "'XSfvfwmaccqqq' (SiFive Matrix Multiply Accumulate Instruction and 4-by-4))">; def FeatureVendorXSfvfnrclipxfqf - : SubtargetFeature<"xsfvfnrclipxfqf", "HasVendorXSfvfnrclipxfqf", "true", - "'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)", - [FeatureStdExtZve32f]>; + : RISCVExtension<"xsfvfnrclipxfqf", 1, 0, + "'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)", + [FeatureStdExtZve32f]>; def HasVendorXSfvfnrclipxfqf : Predicate<"Subtarget->hasVendorXSfvfnrclipxfqf()">, AssemblerPredicate<(all_of FeatureVendorXSfvfnrclipxfqf), "'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)">; def FeatureVendorXSiFivecdiscarddlone - : SubtargetFeature<"xsifivecdiscarddlone", "HasVendorXSiFivecdiscarddlone", "true", - "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)", []>; + : RISCVExtension<"xsifivecdiscarddlone", 1, 0, + "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)", []>; def HasVendorXSiFivecdiscarddlone : Predicate<"Subtarget->hasVendorXSiFivecdiscarddlone()">, AssemblerPredicate<(all_of FeatureVendorXSiFivecdiscarddlone), "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)">; def FeatureVendorXSiFivecflushdlone - : SubtargetFeature<"xsifivecflushdlone", "HasVendorXSiFivecflushdlone", "true", - "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)", []>; + : RISCVExtension<"xsifivecflushdlone", 1, 0, + "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)", []>; def HasVendorXSiFivecflushdlone : Predicate<"Subtarget->hasVendorXSiFivecflushdlone()">, AssemblerPredicate<(all_of FeatureVendorXSiFivecflushdlone), "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)">; def FeatureVendorXSfcease - : SubtargetFeature<"xsfcease", "HasVendorXSfcease", "true", - "'XSfcease' (SiFive sf.cease Instruction)", []>; + : RISCVExtension<"xsfcease", 1, 0, + "'XSfcease' (SiFive sf.cease Instruction)", []>; def HasVendorXSfcease : Predicate<"Subtarget->hasVendorXSfcease()">, AssemblerPredicate<(all_of FeatureVendorXSfcease), @@ -1091,56 +1131,56 @@ def HasVendorXSfcease // Core-V Extensions def FeatureVendorXCVelw - : SubtargetFeature<"xcvelw", "HasVendorXCVelw", "true", - "'XCVelw' (CORE-V Event Load Word)">; + : RISCVExtension<"xcvelw", 1, 0, + "'XCVelw' (CORE-V Event Load Word)">; def HasVendorXCVelw : Predicate<"Subtarget->hasVendorXCVelw()">, AssemblerPredicate<(any_of FeatureVendorXCVelw), "'XCVelw' (CORE-V Event Load Word)">; def FeatureVendorXCVbitmanip - : SubtargetFeature<"xcvbitmanip", "HasVendorXCVbitmanip", "true", - "'XCVbitmanip' (CORE-V Bit Manipulation)">; + : RISCVExtension<"xcvbitmanip", 1, 0, + "'XCVbitmanip' (CORE-V Bit Manipulation)">; def HasVendorXCVbitmanip : Predicate<"Subtarget->hasVendorXCVbitmanip()">, AssemblerPredicate<(all_of FeatureVendorXCVbitmanip), "'XCVbitmanip' (CORE-V Bit Manipulation)">; def FeatureVendorXCVmac - : SubtargetFeature<"xcvmac", "HasVendorXCVmac", "true", - "'XCVmac' (CORE-V Multiply-Accumulate)">; + : RISCVExtension<"xcvmac", 1, 0, + "'XCVmac' (CORE-V Multiply-Accumulate)">; def HasVendorXCVmac : Predicate<"Subtarget->hasVendorXCVmac()">, AssemblerPredicate<(all_of FeatureVendorXCVmac), "'XCVmac' (CORE-V Multiply-Accumulate)">; def FeatureVendorXCVmem - : SubtargetFeature<"xcvmem", "HasVendorXCVmem", "true", - "'XCVmem' (CORE-V Post-incrementing Load & Store)">; + : RISCVExtension<"xcvmem", 1, 0, + "'XCVmem' (CORE-V Post-incrementing Load & Store)">; def HasVendorXCVmem : Predicate<"Subtarget->hasVendorXCVmem()">, AssemblerPredicate<(any_of FeatureVendorXCVmem), "'XCVmem' (CORE-V Post-incrementing Load & Store)">; def FeatureVendorXCValu - : SubtargetFeature<"xcvalu", "HasVendorXCValu", "true", - "'XCValu' (CORE-V ALU Operations)">; + : RISCVExtension<"xcvalu", 1, 0, + "'XCValu' (CORE-V ALU Operations)">; def HasVendorXCValu : Predicate<"Subtarget->hasVendorXCValu()">, AssemblerPredicate<(all_of FeatureVendorXCValu), "'XCValu' (CORE-V ALU Operations)">; def FeatureVendorXCVsimd - : SubtargetFeature<"xcvsimd", "HasVendorXCvsimd", "true", - "'XCVsimd' (CORE-V SIMD ALU)">; + : RISCVExtension<"xcvsimd", 1, 0, + "'XCVsimd' (CORE-V SIMD ALU)">; def HasVendorXCVsimd : Predicate<"Subtarget->hasVendorXCVsimd()">, AssemblerPredicate<(any_of FeatureVendorXCVsimd), "'XCVsimd' (CORE-V SIMD ALU)">; def FeatureVendorXCVbi - : SubtargetFeature<"xcvbi", "HasVendorXCVbi", "true", - "'XCVbi' (CORE-V Immediate Branching)">; + : RISCVExtension<"xcvbi", 1, 0, + "'XCVbi' (CORE-V Immediate Branching)">; def HasVendorXCVbi : Predicate<"Subtarget->hasVendorXCVbi()">, AssemblerPredicate<(all_of FeatureVendorXCVbi), -- GitLab From c1b6cca1214e7a9c14a30b81585dd8b81baeaa77 Mon Sep 17 00:00:00 2001 From: Wentao Zhang <35722712+whentojump@users.noreply.github.com> Date: Mon, 22 Apr 2024 12:37:38 -0500 Subject: [PATCH 199/357] [clang][CoverageMapping] do not emit a gap region when either end doesn't have valid source locations (#89564) Fixes #86998 --- clang/lib/CodeGen/CoverageMappingGen.cpp | 11 ++++-- .../CoverageMapping/statement-expression.c | 36 +++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 clang/test/CoverageMapping/statement-expression.c diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 64c39c5de351..733686d4946b 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1208,6 +1208,12 @@ struct CounterCoverageMappingBuilder /// Find a valid gap range between \p AfterLoc and \p BeforeLoc. std::optional findGapAreaBetween(SourceLocation AfterLoc, SourceLocation BeforeLoc) { + // Some statements (like AttributedStmt and ImplicitValueInitExpr) don't + // have valid source locations. Do not emit a gap region if this is the case + // in either AfterLoc end or BeforeLoc end. + if (AfterLoc.isInvalid() || BeforeLoc.isInvalid()) + return std::nullopt; + // If AfterLoc is in function-like macro, use the right parenthesis // location. if (AfterLoc.isMacroID()) { @@ -1368,9 +1374,8 @@ struct CounterCoverageMappingBuilder for (const Stmt *Child : S->children()) if (Child) { // If last statement contains terminate statements, add a gap area - // between the two statements. Skipping attributed statements, because - // they don't have valid start location. - if (LastStmt && HasTerminateStmt && !isa(Child)) { + // between the two statements. + if (LastStmt && HasTerminateStmt) { auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child)); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), diff --git a/clang/test/CoverageMapping/statement-expression.c b/clang/test/CoverageMapping/statement-expression.c new file mode 100644 index 000000000000..5f9ab5838af3 --- /dev/null +++ b/clang/test/CoverageMapping/statement-expression.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name statement-expression.c %s + +// No crash for the following examples, where GNU Statement Expression extension +// could introduce region terminators (break, goto etc) before implicit +// initializers in a struct or an array. +// See https://github.com/llvm/llvm-project/pull/89564 + +struct Foo { + int field1; + int field2; +}; + +void f1(void) { + struct Foo foo = { + .field1 = ({ + switch (0) { + case 0: + break; // A region terminator + } + 0; + }), + // ImplicitValueInitExpr introduced here for .field2 + }; +} + +void f2(void) { + int arr[3] = { + [0] = ({ + goto L0; // A region terminator +L0: + 0; + }), + // ImplicitValueInitExpr introduced here for subscript [1] + [2] = 0, + }; +} -- GitLab From 92631a4824a91f3268a5716dd3459df8dc6bfb63 Mon Sep 17 00:00:00 2001 From: Miro Bucko Date: Mon, 22 Apr 2024 13:40:06 -0400 Subject: [PATCH 200/357] [lldb][MinidumpFileBuilder] Fix addition of MemoryList steam (#88564) Summary: AddMemoryList() was returning the last error status returned by ReadMemory(). So if an invalid memory region was read last, the function would return an error. Test Plan: ./bin/llvm-lit -sv ~/src/llvm-project/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py Reviewers: kevinfrei,clayborg Subscribers: Tasks: Tags: --- .../ObjectFile/Minidump/MinidumpFileBuilder.cpp | 11 +++++++++-- lldb/source/Target/Process.cpp | 7 +++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp index cefd4cb22b6b..601f11d51d42 100644 --- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp +++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp @@ -21,6 +21,7 @@ #include "lldb/Target/ThreadList.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "llvm/ADT/StringRef.h" @@ -663,14 +664,20 @@ MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp, DataBufferHeap helper_data; std::vector mem_descriptors; for (const auto &core_range : core_ranges) { - // Skip empty memory regions or any regions with no permissions. - if (core_range.range.empty() || core_range.lldb_permissions == 0) + // Skip empty memory regions. + if (core_range.range.empty()) continue; const addr_t addr = core_range.range.start(); const addr_t size = core_range.range.size(); auto data_up = std::make_unique(size, 0); const size_t bytes_read = process_sp->ReadMemory(addr, data_up->GetBytes(), size, error); + if (error.Fail()) { + Log *log = GetLog(LLDBLog::Object); + LLDB_LOGF(log, "Failed to read memory region. Bytes read: %zu, error: %s", + bytes_read, error.AsCString()); + error.Clear(); + } if (bytes_read == 0) continue; // We have a good memory region with valid bytes to store. diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index f02ec37cb0f0..606518ca5412 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -6325,8 +6325,11 @@ static bool AddDirtyPages(const MemoryRegionInfo ®ion, // ranges. static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages, Process::CoreFileMemoryRanges &ranges) { - // Don't add empty ranges or ranges with no permissions. - if (region.GetRange().GetByteSize() == 0 || region.GetLLDBPermissions() == 0) + // Don't add empty ranges. + if (region.GetRange().GetByteSize() == 0) + return; + // Don't add ranges with no read permissions. + if ((region.GetLLDBPermissions() & lldb::ePermissionsReadable) == 0) return; if (try_dirty_pages && AddDirtyPages(region, ranges)) return; -- GitLab From f352ce368af39e57d337495d7ca3a21975ede8e6 Mon Sep 17 00:00:00 2001 From: Michal Paszkowski Date: Mon, 22 Apr 2024 10:47:46 -0700 Subject: [PATCH 201/357] [SPIR-V] Emit SPIR-V generator magic number and version (#87951) This patch: - Adds SPIR-V backend's registered generator magic number to the emitted binary. The magic number consists of the generator ID (43) and LLVM major version. - Adds SPIR-V version to the binary. - Allows reading the expected (maximum supported) SPIR-V version from the target triple. - Uses VersionTuple for representing versions throughout the backend's codebase. - Registers v1.6 for spirv32 and spirv64 triple. See more: https://github.com/KhronosGroup/SPIRV-Headers/commit/7d500c --- llvm/lib/MC/SPIRVObjectWriter.cpp | 6 +-- .../SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp | 12 ++--- .../Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h | 5 +- llvm/lib/Target/SPIRV/SPIRV.td | 13 ----- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 10 ++-- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 52 +++++++++++-------- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h | 20 ++++--- llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp | 43 +++++++++++---- llvm/lib/Target/SPIRV/SPIRVSubtarget.h | 10 ++-- llvm/lib/TargetParser/Triple.cpp | 6 ++- llvm/test/CodeGen/SPIRV/ComparePointers.ll | 4 +- llvm/test/CodeGen/SPIRV/empty-opencl32.ll | 2 - .../SPIRV/exec_mode_float_control_khr.ll | 4 +- .../physical-layout/generator-magic-number.ll | 4 ++ .../SPIRV/physical-layout/spirv-version.ll | 16 ++++++ .../AtomicCompareExchangeExplicit_cl20.ll | 4 +- 16 files changed, 123 insertions(+), 88 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/physical-layout/generator-magic-number.ll create mode 100644 llvm/test/CodeGen/SPIRV/physical-layout/spirv-version.ll diff --git a/llvm/lib/MC/SPIRVObjectWriter.cpp b/llvm/lib/MC/SPIRVObjectWriter.cpp index d72d6e07f2e6..5d85c5de4e4e 100644 --- a/llvm/lib/MC/SPIRVObjectWriter.cpp +++ b/llvm/lib/MC/SPIRVObjectWriter.cpp @@ -43,10 +43,10 @@ private: void SPIRVObjectWriter::writeHeader(const MCAssembler &Asm) { constexpr uint32_t MagicNumber = 0x07230203; - constexpr uint32_t GeneratorMagicNumber = 0; + constexpr uint32_t GeneratorID = 43; + constexpr uint32_t GeneratorMagicNumber = + (GeneratorID << 16) | (LLVM_VERSION_MAJOR); constexpr uint32_t Schema = 0; - - // Construct SPIR-V version and Bound const MCAssembler::VersionInfoType &VIT = Asm.getVersionInfo(); uint32_t VersionNumber = 0 | (VIT.Major << 16) | (VIT.Minor << 8); uint32_t Bound = VIT.Update; diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp index b69031adb167..d96d2bf31b62 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp @@ -88,28 +88,28 @@ getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, return Name; } -uint32_t +VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value) { const SPIRV::SymbolicOperand *Lookup = SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); if (Lookup) - return Lookup->MinVersion; + return VersionTuple(Lookup->MinVersion / 10, Lookup->MinVersion % 10); - return 0; + return VersionTuple(0); } -uint32_t +VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value) { const SPIRV::SymbolicOperand *Lookup = SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); if (Lookup) - return Lookup->MaxVersion; + return VersionTuple(Lookup->MaxVersion / 10, Lookup->MaxVersion % 10); - return 0; + return VersionTuple(); } CapabilityList diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h index 616d2ea71b39..990eb1d230bc 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" #include namespace llvm { @@ -214,10 +215,10 @@ using ExtensionList = SmallVector; std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value); -uint32_t +VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value); -uint32_t +VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value); CapabilityList diff --git a/llvm/lib/Target/SPIRV/SPIRV.td b/llvm/lib/Target/SPIRV/SPIRV.td index beb55d05307c..108c7e6d3861 100644 --- a/llvm/lib/Target/SPIRV/SPIRV.td +++ b/llvm/lib/Target/SPIRV/SPIRV.td @@ -20,19 +20,6 @@ class Proc Features> def : Proc<"generic", []>; -def SPIRV10 : SubtargetFeature<"spirv1.0", "SPIRVVersion", "10", - "Use SPIR-V version 1.0">; -def SPIRV11 : SubtargetFeature<"spirv1.1", "SPIRVVersion", "11", - "Use SPIR-V version 1.1">; -def SPIRV12 : SubtargetFeature<"spirv1.2", "SPIRVVersion", "12", - "Use SPIR-V version 1.2">; -def SPIRV13 : SubtargetFeature<"spirv1.3", "SPIRVVersion", "13", - "Use SPIR-V version 1.3">; -def SPIRV14 : SubtargetFeature<"spirv1.4", "SPIRVVersion", "14", - "Use SPIR-V version 1.4">; -def SPIRV15 : SubtargetFeature<"spirv1.5", "SPIRVVersion", "15", - "Use SPIR-V version 1.5">; - def SPIRVInstPrinter : AsmWriter { string AsmWriterClassName = "InstPrinter"; bit isMCAsmWriter = 1; diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index 1de4616fd5b7..2ebe5bdc4771 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -108,9 +108,9 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { } ST = static_cast(TM).getSubtargetImpl(); - uint32_t DecSPIRVVersion = ST->getSPIRVVersion(); - uint32_t Major = DecSPIRVVersion / 10; - uint32_t Minor = DecSPIRVVersion - Major * 10; + VersionTuple SPIRVVersion = ST->getSPIRVVersion(); + uint32_t Major = SPIRVVersion.getMajor(); + uint32_t Minor = SPIRVVersion.getMinor().value_or(0); // Bound is an approximation that accounts for the maximum used register // number and number of generated OpLabels unsigned Bound = 2 * (ST->getBound() + 1) + NLabels; @@ -321,8 +321,8 @@ void SPIRVAsmPrinter::outputEntryPoints() { // the Input and Output storage classes. Starting with version 1.4, // the interface's storage classes are all storage classes used in // declaring all global variables referenced by the entry point call tree. - if (ST->getSPIRVVersion() >= 14 || SC == SPIRV::StorageClass::Input || - SC == SPIRV::StorageClass::Output) { + if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) || + SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) { MachineFunction *MF = MI->getMF(); Register Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg()); InterfaceIDs.insert(Reg); diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 8395d4b2bf66..235f947901d8 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -76,18 +76,20 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, SPIRV::RequirementHandler &Reqs) { static AvoidCapabilitiesSet AvoidCaps; // contains capabilities to avoid if there is another option - unsigned ReqMinVer = getSymbolicOperandMinVersion(Category, i); - unsigned ReqMaxVer = getSymbolicOperandMaxVersion(Category, i); - unsigned TargetVer = ST.getSPIRVVersion(); - bool MinVerOK = !ReqMinVer || !TargetVer || TargetVer >= ReqMinVer; - bool MaxVerOK = !ReqMaxVer || !TargetVer || TargetVer <= ReqMaxVer; + + VersionTuple ReqMinVer = getSymbolicOperandMinVersion(Category, i); + VersionTuple ReqMaxVer = getSymbolicOperandMaxVersion(Category, i); + VersionTuple SPIRVVersion = ST.getSPIRVVersion(); + bool MinVerOK = SPIRVVersion.empty() || SPIRVVersion >= ReqMinVer; + bool MaxVerOK = + ReqMaxVer.empty() || SPIRVVersion.empty() || SPIRVVersion <= ReqMaxVer; CapabilityList ReqCaps = getSymbolicOperandCapabilities(Category, i); ExtensionList ReqExts = getSymbolicOperandExtensions(Category, i); if (ReqCaps.empty()) { if (ReqExts.empty()) { if (MinVerOK && MaxVerOK) return {true, {}, {}, ReqMinVer, ReqMaxVer}; - return {false, {}, {}, 0, 0}; + return {false, {}, {}, VersionTuple(), VersionTuple()}; } } else if (MinVerOK && MaxVerOK) { if (ReqCaps.size() == 1) { @@ -118,9 +120,13 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, if (llvm::all_of(ReqExts, [&ST](const SPIRV::Extension::Extension &Ext) { return ST.canUseExtension(Ext); })) { - return {true, {}, ReqExts, 0, 0}; // TODO: add versions to extensions. + return {true, + {}, + ReqExts, + VersionTuple(), + VersionTuple()}; // TODO: add versions to extensions. } - return {false, {}, {}, 0, 0}; + return {false, {}, {}, VersionTuple(), VersionTuple()}; } void SPIRVModuleAnalysis::setBaseInfo(const Module &M) { @@ -510,25 +516,25 @@ void SPIRV::RequirementHandler::addRequirements( addExtensions(Req.Exts); - if (Req.MinVer) { - if (MaxVersion && Req.MinVer > MaxVersion) { + if (!Req.MinVer.empty()) { + if (!MaxVersion.empty() && Req.MinVer > MaxVersion) { LLVM_DEBUG(dbgs() << "Conflicting version requirements: >= " << Req.MinVer << " and <= " << MaxVersion << "\n"); report_fatal_error("Adding SPIR-V requirements that can't be satisfied."); } - if (MinVersion == 0 || Req.MinVer > MinVersion) + if (MinVersion.empty() || Req.MinVer > MinVersion) MinVersion = Req.MinVer; } - if (Req.MaxVer) { - if (MinVersion && Req.MaxVer < MinVersion) { + if (!Req.MaxVer.empty()) { + if (!MinVersion.empty() && Req.MaxVer < MinVersion) { LLVM_DEBUG(dbgs() << "Conflicting version requirements: <= " << Req.MaxVer << " and >= " << MinVersion << "\n"); report_fatal_error("Adding SPIR-V requirements that can't be satisfied."); } - if (MaxVersion == 0 || Req.MaxVer < MaxVersion) + if (MaxVersion.empty() || Req.MaxVer < MaxVersion) MaxVersion = Req.MaxVer; } } @@ -539,7 +545,7 @@ void SPIRV::RequirementHandler::checkSatisfiable( bool IsSatisfiable = true; auto TargetVer = ST.getSPIRVVersion(); - if (MaxVersion && TargetVer && MaxVersion < TargetVer) { + if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) { LLVM_DEBUG( dbgs() << "Target SPIR-V version too high for required features\n" << "Required max version: " << MaxVersion << " target version " @@ -547,14 +553,14 @@ void SPIRV::RequirementHandler::checkSatisfiable( IsSatisfiable = false; } - if (MinVersion && TargetVer && MinVersion > TargetVer) { + if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) { LLVM_DEBUG(dbgs() << "Target SPIR-V version too low for required features\n" << "Required min version: " << MinVersion << " target version " << TargetVer << "\n"); IsSatisfiable = false; } - if (MinVersion && MaxVersion && MinVersion > MaxVersion) { + if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) { LLVM_DEBUG( dbgs() << "Version is too low for some features and too high for others.\n" @@ -632,12 +638,13 @@ void RequirementHandler::initAvailableCapabilitiesForOpenCL( addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler, Capability::Image1D, Capability::SampledBuffer, Capability::ImageBuffer}); - if (ST.isAtLeastOpenCLVer(20)) + if (ST.isAtLeastOpenCLVer(VersionTuple(2, 0))) addAvailableCaps({Capability::ImageReadWrite}); } - if (ST.isAtLeastSPIRVVer(11) && ST.isAtLeastOpenCLVer(22)) + if (ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) && + ST.isAtLeastOpenCLVer(VersionTuple(2, 2))) addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage}); - if (ST.isAtLeastSPIRVVer(13)) + if (ST.isAtLeastSPIRVVer(VersionTuple(1, 3))) addAvailableCaps({Capability::GroupNonUniform, Capability::GroupNonUniformVote, Capability::GroupNonUniformArithmetic, @@ -645,7 +652,7 @@ void RequirementHandler::initAvailableCapabilitiesForOpenCL( Capability::GroupNonUniformClustered, Capability::GroupNonUniformShuffle, Capability::GroupNonUniformShuffleRelative}); - if (ST.isAtLeastSPIRVVer(14)) + if (ST.isAtLeastSPIRVVer(VersionTuple(1, 4))) addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero, Capability::SignedZeroInfNanPreserve, Capability::RoundingModeRTE, @@ -1162,7 +1169,8 @@ static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, auto Node = M.getNamedMetadata("spirv.ExecutionMode"); if (Node) { // SPV_KHR_float_controls is not available until v1.4 - bool RequireFloatControls = false, VerLower14 = !ST.isAtLeastSPIRVVer(14); + bool RequireFloatControls = false, + VerLower14 = !ST.isAtLeastSPIRVVer(VersionTuple(1, 4)); for (unsigned i = 0; i < Node->getNumOperands(); i++) { MDNode *MDN = cast(Node->getOperand(i)); const MDOperand &MDOp = MDN->getOperand(1); diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h index 6e86eed30c5d..79226d6d93ef 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h @@ -45,13 +45,13 @@ struct Requirements { const bool IsSatisfiable; const std::optional Cap; const ExtensionList Exts; - const unsigned MinVer; // 0 if no min version is required. - const unsigned MaxVer; // 0 if no max version is required. + const VersionTuple MinVer; // 0 if no min version is required. + const VersionTuple MaxVer; // 0 if no max version is required. Requirements(bool IsSatisfiable = false, std::optional Cap = {}, - ExtensionList Exts = {}, unsigned MinVer = 0, - unsigned MaxVer = 0) + ExtensionList Exts = {}, VersionTuple MinVer = VersionTuple(), + VersionTuple MaxVer = VersionTuple()) : IsSatisfiable(IsSatisfiable), Cap(Cap), Exts(Exts), MinVer(MinVer), MaxVer(MaxVer) {} Requirements(Capability::Capability Cap) : Requirements(true, {Cap}) {} @@ -69,8 +69,8 @@ private: DenseSet AvailableCaps; SmallSet AllExtensions; - unsigned MinVersion; // 0 if no min version is defined. - unsigned MaxVersion; // 0 if no max version is defined. + VersionTuple MinVersion; // 0 if no min version is defined. + VersionTuple MaxVersion; // 0 if no max version is defined. // Add capabilities to AllCaps, recursing through their implicitly declared // capabilities too. void recursiveAddCapabilities(const CapabilityList &ToPrune); @@ -79,17 +79,15 @@ private: void initAvailableCapabilitiesForVulkan(const SPIRVSubtarget &ST); public: - RequirementHandler() : MinVersion(0), MaxVersion(0) {} + RequirementHandler() {} void clear() { MinimalCaps.clear(); AllCaps.clear(); AvailableCaps.clear(); AllExtensions.clear(); - MinVersion = 0; - MaxVersion = 0; + MinVersion = VersionTuple(); + MaxVersion = VersionTuple(); } - unsigned getMinVersion() const { return MinVersion; } - unsigned getMaxVersion() const { return MaxVersion; } const CapabilityList &getMinimalCapabilities() const { return MinimalCaps; } const SmallSet &getExtensions() const { return AllExtensions; diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index f3864b56e1e9..7aa0c566c75f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -39,18 +39,43 @@ static cl::opt, false, cl::desc("Specify list of enabled SPIR-V extensions")); // Compare version numbers, but allow 0 to mean unspecified. -static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { - return Target == 0 || Target >= VerToCompareTo; +static bool isAtLeastVer(VersionTuple Target, VersionTuple VerToCompareTo) { + return Target.empty() || Target >= VerToCompareTo; } SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const SPIRVTargetMachine &TM) : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), - PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), SPIRVVersion(0), - OpenCLVersion(0), InstrInfo(), + PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), InstrInfo(), FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), TargetTriple(TT) { + switch (TT.getSubArch()) { + case Triple::SPIRVSubArch_v10: + SPIRVVersion = VersionTuple(1, 0); + break; + case Triple::SPIRVSubArch_v11: + SPIRVVersion = VersionTuple(1, 1); + break; + case Triple::SPIRVSubArch_v12: + SPIRVVersion = VersionTuple(1, 2); + break; + case Triple::SPIRVSubArch_v13: + SPIRVVersion = VersionTuple(1, 3); + break; + case Triple::SPIRVSubArch_v14: + default: + SPIRVVersion = VersionTuple(1, 4); + break; + case Triple::SPIRVSubArch_v15: + SPIRVVersion = VersionTuple(1, 5); + break; + case Triple::SPIRVSubArch_v16: + SPIRVVersion = VersionTuple(1, 6); + break; + } + OpenCLVersion = VersionTuple(2, 2); + // The order of initialization is important. initAvailableExtensions(); initAvailableExtInstSets(); @@ -66,10 +91,6 @@ SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU, SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU, StringRef FS) { ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS); - if (SPIRVVersion == 0) - SPIRVVersion = 14; - if (OpenCLVersion == 0) - OpenCLVersion = 22; return *this; } @@ -82,11 +103,11 @@ bool SPIRVSubtarget::canUseExtInstSet( return AvailableExtInstSets.contains(E); } -bool SPIRVSubtarget::isAtLeastSPIRVVer(uint32_t VerToCompareTo) const { +bool SPIRVSubtarget::isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const { return isAtLeastVer(SPIRVVersion, VerToCompareTo); } -bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { +bool SPIRVSubtarget::isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const { if (!isOpenCLEnv()) return false; return isAtLeastVer(OpenCLVersion, VerToCompareTo); @@ -95,7 +116,7 @@ bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. // In SPIR-V Translator compatibility mode this feature is not available. bool SPIRVSubtarget::canDirectlyComparePointers() const { - return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, 14); + return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, VersionTuple(1, 4)); } void SPIRVSubtarget::initAvailableExtensions() { diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h index 3b486226a939..3e4044084266 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h @@ -37,8 +37,8 @@ class SPIRVTargetMachine; class SPIRVSubtarget : public SPIRVGenSubtargetInfo { private: const unsigned PointerSize; - uint32_t SPIRVVersion; - uint32_t OpenCLVersion; + VersionTuple SPIRVVersion; + VersionTuple OpenCLVersion; SmallSet AvailableExtensions; SmallSet AvailableExtInstSets; @@ -81,9 +81,9 @@ public: TargetTriple.getArch() == Triple::spirv64; } bool isVulkanEnv() const { return TargetTriple.getArch() == Triple::spirv; } - uint32_t getSPIRVVersion() const { return SPIRVVersion; }; - bool isAtLeastSPIRVVer(uint32_t VerToCompareTo) const; - bool isAtLeastOpenCLVer(uint32_t VerToCompareTo) const; + VersionTuple getSPIRVVersion() const { return SPIRVVersion; }; + bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const; + bool isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const; // TODO: implement command line args or other ways to determine this. bool hasOpenCLFullProfile() const { return true; } bool hasOpenCLImageSupport() const { return true; } diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 77fdf31d4865..2c5aee3dfb2f 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -559,9 +559,11 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("spir64", Triple::spir64) .Cases("spirv", "spirv1.5", "spirv1.6", Triple::spirv) .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2", - "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", Triple::spirv32) + "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", + "spirv32v1.6", Triple::spirv32) .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", - "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", Triple::spirv64) + "spirv64v1.3", "spirv64v1.4", "spirv64v1.5", + "spirv64v1.6", Triple::spirv64) .StartsWith("kalimba", Triple::kalimba) .Case("lanai", Triple::lanai) .Case("renderscript32", Triple::renderscript32) diff --git a/llvm/test/CodeGen/SPIRV/ComparePointers.ll b/llvm/test/CodeGen/SPIRV/ComparePointers.ll index 6777fc38024b..408b95579502 100644 --- a/llvm/test/CodeGen/SPIRV/ComparePointers.ll +++ b/llvm/test/CodeGen/SPIRV/ComparePointers.ll @@ -1,5 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --mattr=+spirv1.3 %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; kernel void test(int global *in, int global *in2) { ;; if (!in) diff --git a/llvm/test/CodeGen/SPIRV/empty-opencl32.ll b/llvm/test/CodeGen/SPIRV/empty-opencl32.ll index 8e826ec35f37..5b007c7e8adc 100644 --- a/llvm/test/CodeGen/SPIRV/empty-opencl32.ll +++ b/llvm/test/CodeGen/SPIRV/empty-opencl32.ll @@ -1,8 +1,6 @@ ; 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 %} -;; FIXME: ensure Magic Number, version number, generator's magic number, "bound" and "schema" are at least present - ;; Ensure the required Capabilities are listed. ; CHECK-DAG: OpCapability Kernel ; CHECK-DAG: OpCapability Addresses diff --git a/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll b/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll index 721e825a1c98..d3131e560685 100644 --- a/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll +++ b/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll @@ -1,5 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=SPV -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s --mattr=+spirv1.3 --spirv-ext=+SPV_KHR_float_controls -o - | FileCheck %s --check-prefixes=SPVEXT +; RUN: llc -O0 -mtriple=spirv32v1.3-unknown-unknown %s -o - | FileCheck %s --check-prefixes=SPV +; RUN: llc -O0 -mtriple=spirv32v1.3-unknown-unknown %s --spirv-ext=+SPV_KHR_float_controls -o - | FileCheck %s --check-prefixes=SPVEXT define dso_local dllexport spir_kernel void @k_float_controls_0(i32 %ibuf, i32 %obuf) local_unnamed_addr { entry: diff --git a/llvm/test/CodeGen/SPIRV/physical-layout/generator-magic-number.ll b/llvm/test/CodeGen/SPIRV/physical-layout/generator-magic-number.ll new file mode 100644 index 000000000000..afffd9e69b45 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/physical-layout/generator-magic-number.ll @@ -0,0 +1,4 @@ +; REQUIRES: spirv-tools +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s + +; CHECK: Generator: {{.*}}{{43|LLVM SPIR-V Backend}}{{.*}} diff --git a/llvm/test/CodeGen/SPIRV/physical-layout/spirv-version.ll b/llvm/test/CodeGen/SPIRV/physical-layout/spirv-version.ll new file mode 100644 index 000000000000..686c1e97257a --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/physical-layout/spirv-version.ll @@ -0,0 +1,16 @@ +; REQUIRES: spirv-tools +; RUN: llc -O0 -mtriple=spirv64v1.0-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV10 +; RUN: llc -O0 -mtriple=spirv64v1.1-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV11 +; RUN: llc -O0 -mtriple=spirv64v1.2-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV12 +; RUN: llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV13 +; RUN: llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV14 +; RUN: llc -O0 -mtriple=spirv64v1.5-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV15 +; RUN: llc -O0 -mtriple=spirv64v1.6-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s --check-prefix=CHECK-SPIRV16 + +; CHECK-SPIRV10: Version: 1.0 +; CHECK-SPIRV11: Version: 1.1 +; CHECK-SPIRV12: Version: 1.2 +; CHECK-SPIRV13: Version: 1.3 +; CHECK-SPIRV14: Version: 1.4 +; CHECK-SPIRV15: Version: 1.5 +; CHECK-SPIRV16: Version: 1.6 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll b/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll index e0c47798cc6d..cb5bce1375b6 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll @@ -1,5 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --mattr=+spirv1.3 %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --mattr=+spirv1.3 %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32v1.3-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32v1.3-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; __kernel void testAtomicCompareExchangeExplicit_cl20( ;; volatile global atomic_int* object, -- GitLab From 9c9dea943706340f8a45dc74887bf9beddd67810 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Apr 2024 13:04:20 -0500 Subject: [PATCH 202/357] [flang][OpenMP] Concatenate begin and end clauses into single list (#89090) This will remove the distinction between begin clauses and end clauses, and process all of them together. --- flang/lib/Lower/OpenMP/OpenMP.cpp | 253 +++++++++++++----------------- 1 file changed, 110 insertions(+), 143 deletions(-) diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index db99617a7ba9..e932f7c284bc 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1089,16 +1089,12 @@ static void genParallelClauses( static void genSectionsClauses(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, - bool clausesFromBeginSections, mlir::omp::SectionsClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); - if (clausesFromBeginSections) { - cp.processAllocate(clauseOps); - cp.processSectionsReduction(loc, clauseOps); - // TODO Support delayed privatization. - } else { - cp.processNowait(clauseOps); - } + cp.processAllocate(clauseOps); + cp.processSectionsReduction(loc, clauseOps); + cp.processNowait(clauseOps); + // TODO Support delayed privatization. } static void genSimdClauses(Fortran::lower::AbstractConverter &converter, @@ -1119,16 +1115,13 @@ static void genSimdClauses(Fortran::lower::AbstractConverter &converter, static void genSingleClauses(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, - const List &beginClauses, - const List &endClauses, mlir::Location loc, + const List &clauses, mlir::Location loc, mlir::omp::SingleClauseOps &clauseOps) { - ClauseProcessor bcp(converter, semaCtx, beginClauses); - bcp.processAllocate(clauseOps); + ClauseProcessor cp(converter, semaCtx, clauses); + cp.processAllocate(clauseOps); + cp.processCopyprivate(loc, clauseOps); + cp.processNowait(clauseOps); // TODO Support delayed privatization. - - ClauseProcessor ecp(converter, semaCtx, endClauses); - ecp.processCopyprivate(loc, clauseOps); - ecp.processNowait(clauseOps); } static void genTargetClauses( @@ -1278,30 +1271,25 @@ static void genWsloopClauses( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::StatementContext &stmtCtx, - Fortran::lower::pft::Evaluation &eval, const List &beginClauses, - const List &endClauses, mlir::Location loc, - mlir::omp::WsloopClauseOps &clauseOps, + Fortran::lower::pft::Evaluation &eval, const List &clauses, + mlir::Location loc, mlir::omp::WsloopClauseOps &clauseOps, llvm::SmallVectorImpl &iv, llvm::SmallVectorImpl &reductionTypes, llvm::SmallVectorImpl &reductionSyms) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - ClauseProcessor bcp(converter, semaCtx, beginClauses); - bcp.processCollapse(loc, eval, clauseOps, iv); - bcp.processOrdered(clauseOps); - bcp.processReduction(loc, clauseOps, &reductionTypes, &reductionSyms); - bcp.processSchedule(stmtCtx, clauseOps); + ClauseProcessor cp(converter, semaCtx, clauses); + cp.processCollapse(loc, eval, clauseOps, iv); + cp.processNowait(clauseOps); + cp.processOrdered(clauseOps); + cp.processReduction(loc, clauseOps, &reductionTypes, &reductionSyms); + cp.processSchedule(stmtCtx, clauseOps); clauseOps.loopInclusiveAttr = firOpBuilder.getUnitAttr(); // TODO Support delayed privatization. if (ReductionProcessor::doReductionByRef(clauseOps.reductionVars)) clauseOps.reductionByRefAttr = firOpBuilder.getUnitAttr(); - if (!endClauses.empty()) { - ClauseProcessor ecp(converter, semaCtx, endClauses); - ecp.processNowait(clauseOps); - } - - bcp.processTODO( + cp.processTODO( loc, llvm::omp::Directive::OMPD_do); } @@ -1555,17 +1543,15 @@ static mlir::omp::SingleOp genSingleOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location loc, const List &beginClauses, - const List &endClauses) { + mlir::Location loc, const List &clauses) { mlir::omp::SingleClauseOps clauseOps; - genSingleClauses(converter, semaCtx, beginClauses, endClauses, loc, - clauseOps); + genSingleClauses(converter, semaCtx, clauses, loc, clauseOps); return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, loc, eval, llvm::omp::Directive::OMPD_single) .setGenNested(genNested) - .setClauses(&beginClauses), + .setClauses(&clauses), clauseOps); } @@ -1814,8 +1800,8 @@ static mlir::omp::WsloopOp genWsloopOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const List &beginClauses, const List &endClauses) { - DataSharingProcessor dsp(converter, semaCtx, beginClauses, eval); + const List &clauses) { + DataSharingProcessor dsp(converter, semaCtx, clauses, eval); dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; @@ -1823,10 +1809,10 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector iv; llvm::SmallVector reductionTypes; llvm::SmallVector reductionSyms; - genWsloopClauses(converter, semaCtx, stmtCtx, eval, beginClauses, endClauses, - loc, clauseOps, iv, reductionTypes, reductionSyms); + genWsloopClauses(converter, semaCtx, stmtCtx, eval, clauses, loc, clauseOps, + iv, reductionTypes, reductionSyms); - auto *nestedEval = getCollapsedLoopEval(eval, getCollapseValue(beginClauses)); + auto *nestedEval = getCollapsedLoopEval(eval, getCollapseValue(clauses)); auto ivCallback = [&](mlir::Operation *op) { return genLoopAndReductionVars(op, converter, loc, iv, reductionSyms, @@ -1836,7 +1822,7 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, return genOpWithBody( OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval, llvm::omp::Directive::OMPD_do) - .setClauses(&beginClauses) + .setClauses(&clauses) .setDataSharingProcessor(&dsp) .setReductions(&reductionSyms, &reductionTypes) .setGenRegionEntryCb(ivCallback), @@ -1847,19 +1833,20 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, // Code generation functions for composite constructs //===----------------------------------------------------------------------===// -static void genCompositeDistributeParallelDo( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &beginClauses, - const List &endClauses, mlir::Location loc) { +static void +genCompositeDistributeParallelDo(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const List &clauses, + mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } static void genCompositeDistributeParallelDoSimd( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &beginClauses, - const List &endClauses, mlir::Location loc) { + Fortran::lower::pft::Evaluation &eval, const List &clauses, + mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } @@ -1867,18 +1854,16 @@ static void genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &beginClauses, - const List &endClauses, mlir::Location loc) { + const List &clauses, mlir::Location loc) { TODO(loc, "Composite DISTRIBUTE SIMD"); } static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &beginClauses, - const List &endClauses, + const List &clauses, mlir::Location loc) { - ClauseProcessor cp(converter, semaCtx, beginClauses); + ClauseProcessor cp(converter, semaCtx, clauses); cp.processTODO( loc, llvm::omp::OMPD_do_simd); @@ -1890,15 +1875,14 @@ static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - genWsloopOp(converter, semaCtx, eval, loc, beginClauses, endClauses); + genWsloopOp(converter, semaCtx, eval, loc, clauses); } static void genCompositeTaskloopSimd(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const List &beginClauses, - const List &endClauses, mlir::Location loc) { + const List &clauses, mlir::Location loc) { TODO(loc, "Composite TASKLOOP SIMD"); } @@ -2170,49 +2154,44 @@ genOMP(Fortran::lower::AbstractConverter &converter, converter.genLocation(beginBlockDirective.source); const auto origDirective = std::get(beginBlockDirective.t).v; - List beginClauses = makeClauses( + List clauses = makeClauses( std::get(beginBlockDirective.t), semaCtx); - List endClauses = makeClauses( - std::get(endBlockDirective.t), semaCtx); + clauses.append(makeClauses( + std::get(endBlockDirective.t), semaCtx)); assert(llvm::omp::blockConstructSet.test(origDirective) && "Expected block construct"); - for (const Clause &clause : beginClauses) { + for (const Clause &clause : clauses) { mlir::Location clauseLocation = converter.genLocation(clause.source); - if (!std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u) && - !std::get_if(&clause.u)) { + if (!std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u)) { TODO(clauseLocation, "OpenMP Block construct clause"); } } - for (const Clause &clause : endClauses) { - mlir::Location clauseLocation = converter.genLocation(clause.source); - if (!std::get_if(&clause.u) && - !std::get_if(&clause.u)) - TODO(clauseLocation, "OpenMP Block construct clause"); - } - std::optional nextDir = origDirective; bool outermostLeafConstruct = true; while (nextDir) { @@ -2228,44 +2207,42 @@ genOMP(Fortran::lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_ordered: // 2.17.9 ORDERED construct. genOrderedRegionOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_parallel: // 2.6 PARALLEL construct. genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, beginClauses, outerCombined); + currentLocation, clauses, outerCombined); break; case llvm::omp::Directive::OMPD_single: // 2.8.2 SINGLE construct. genSingleOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, endClauses); + clauses); break; case llvm::omp::Directive::OMPD_target: // 2.12.5 TARGET construct. - genTargetOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, outerCombined); + genTargetOp(converter, semaCtx, eval, genNested, currentLocation, clauses, + outerCombined); break; case llvm::omp::Directive::OMPD_target_data: // 2.12.2 TARGET DATA construct. genTargetDataOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_task: // 2.10.1 TASK construct. - genTaskOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + genTaskOp(converter, semaCtx, eval, genNested, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_taskgroup: // 2.17.6 TASKGROUP construct. genTaskgroupOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_teams: // 2.7 TEAMS construct. // FIXME Pass the outerCombined argument or rename it to better describe // what it represents if it must always be `false` in this context. - genTeamsOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + genTeamsOp(converter, semaCtx, eval, genNested, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_workshare: // 2.8.3 WORKSHARE construct. @@ -2273,7 +2250,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, // implementation for this feature will come later. For the codes // that use this construct, add a single construct for now. genSingleOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, endClauses); + clauses); break; default: llvm_unreachable("Unexpected block construct"); @@ -2315,7 +2292,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { const auto &beginLoopDirective = std::get(loopConstruct.t); - List beginClauses = makeClauses( + List clauses = makeClauses( std::get(beginLoopDirective.t), semaCtx); mlir::Location currentLocation = converter.genLocation(beginLoopDirective.source); @@ -2325,16 +2302,13 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, assert(llvm::omp::loopConstructSet.test(origDirective) && "Expected loop construct"); - List endClauses = [&]() { - if (auto &endLoopDirective = - std::get>( - loopConstruct.t)) { - return makeClauses( - std::get(endLoopDirective->t), - semaCtx); - } - return List{}; - }(); + if (auto &endLoopDirective = + std::get>( + loopConstruct.t)) { + clauses.append(makeClauses( + std::get(endLoopDirective->t), + semaCtx)); + } std::optional nextDir = origDirective; while (nextDir) { @@ -2345,29 +2319,27 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, switch (leafDir) { case llvm::omp::Directive::OMPD_distribute_parallel_do: // 2.9.4.3 DISTRIBUTE PARALLEL Worksharing-Loop construct. - genCompositeDistributeParallelDo(converter, semaCtx, eval, beginClauses, - endClauses, currentLocation); + genCompositeDistributeParallelDo(converter, semaCtx, eval, clauses, + currentLocation); break; case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: // 2.9.4.4 DISTRIBUTE PARALLEL Worksharing-Loop SIMD construct. - genCompositeDistributeParallelDoSimd(converter, semaCtx, eval, - beginClauses, endClauses, + genCompositeDistributeParallelDoSimd(converter, semaCtx, eval, clauses, currentLocation); break; case llvm::omp::Directive::OMPD_distribute_simd: // 2.9.4.2 DISTRIBUTE SIMD construct. - genCompositeDistributeSimd(converter, semaCtx, eval, beginClauses, - endClauses, currentLocation); + genCompositeDistributeSimd(converter, semaCtx, eval, clauses, + currentLocation); break; case llvm::omp::Directive::OMPD_do_simd: // 2.9.3.2 Worksharing-Loop SIMD construct. - genCompositeDoSimd(converter, semaCtx, eval, beginClauses, endClauses, - currentLocation); + genCompositeDoSimd(converter, semaCtx, eval, clauses, currentLocation); break; case llvm::omp::Directive::OMPD_taskloop_simd: // 2.10.3 TASKLOOP SIMD construct. - genCompositeTaskloopSimd(converter, semaCtx, eval, beginClauses, - endClauses, currentLocation); + genCompositeTaskloopSimd(converter, semaCtx, eval, clauses, + currentLocation); break; default: llvm_unreachable("Unexpected composite construct"); @@ -2378,12 +2350,11 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_distribute: // 2.9.4.1 DISTRIBUTE construct. genDistributeOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses); + clauses); break; case llvm::omp::Directive::OMPD_do: // 2.9.2 Worksharing-Loop construct. - genWsloopOp(converter, semaCtx, eval, currentLocation, beginClauses, - endClauses); + genWsloopOp(converter, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_parallel: // 2.6 PARALLEL construct. @@ -2392,21 +2363,21 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, // Maybe rename the argument if it represents something else or // initialize it properly. genParallelOp(converter, symTable, semaCtx, eval, genNested, - currentLocation, beginClauses, + currentLocation, clauses, /*outerCombined=*/true); break; case llvm::omp::Directive::OMPD_simd: // 2.9.3.1 SIMD construct. - genSimdOp(converter, semaCtx, eval, currentLocation, beginClauses); + genSimdOp(converter, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_target: // 2.12.5 TARGET construct. genTargetOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, /*outerCombined=*/true); + clauses, /*outerCombined=*/true); break; case llvm::omp::Directive::OMPD_taskloop: // 2.10.2 TASKLOOP construct. - genTaskloopOp(converter, semaCtx, eval, currentLocation, beginClauses); + genTaskloopOp(converter, semaCtx, eval, currentLocation, clauses); break; case llvm::omp::Directive::OMPD_teams: // 2.7 TEAMS construct. @@ -2415,7 +2386,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, // Maybe rename the argument if it represents something else or // initialize it properly. genTeamsOp(converter, semaCtx, eval, genNested, currentLocation, - beginClauses, /*outerCombined=*/true); + clauses, /*outerCombined=*/true); break; case llvm::omp::Directive::OMPD_loop: case llvm::omp::Directive::OMPD_masked: @@ -2451,16 +2422,20 @@ genOMP(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OpenMPSectionsConstruct §ionsConstruct) { const auto &beginSectionsDirective = std::get(sectionsConstruct.t); - List beginClauses = makeClauses( + List clauses = makeClauses( std::get(beginSectionsDirective.t), semaCtx); + const auto &endSectionsDirective = + std::get(sectionsConstruct.t); + clauses.append(makeClauses( + std::get(endSectionsDirective.t), + semaCtx)); // Process clauses before optional omp.parallel, so that new variables are // allocated outside of the parallel region mlir::Location currentLocation = converter.getCurrentLocation(); mlir::omp::SectionsClauseOps clauseOps; - genSectionsClauses(converter, semaCtx, beginClauses, currentLocation, - /*clausesFromBeginSections=*/true, clauseOps); + genSectionsClauses(converter, semaCtx, clauses, currentLocation, clauseOps); // Parallel wrapper of PARALLEL SECTIONS construct llvm::omp::Directive dir = @@ -2468,16 +2443,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, .v; if (dir == llvm::omp::Directive::OMPD_parallel_sections) { genParallelOp(converter, symTable, semaCtx, eval, - /*genNested=*/false, currentLocation, beginClauses, + /*genNested=*/false, currentLocation, clauses, /*outerCombined=*/true); - } else { - const auto &endSectionsDirective = - std::get(sectionsConstruct.t); - List endClauses = makeClauses( - std::get(endSectionsDirective.t), - semaCtx); - genSectionsClauses(converter, semaCtx, endClauses, currentLocation, - /*clausesFromBeginSections=*/false, clauseOps); } // SECTIONS construct. @@ -2492,7 +2459,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) { symTable.pushScope(); genSectionOp(converter, semaCtx, neval, /*genNested=*/true, currentLocation, - beginClauses); + clauses); symTable.popScope(); firOpBuilder.restoreInsertionPoint(ip); } -- GitLab From f94ed6f7977305db8fa6b48a85c9db2b8cc4d3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix-Antoine=20Constantin?= <60141446+felix642@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:05:32 -0400 Subject: [PATCH 203/357] [clang-tidy] Improved --verify-config when using literal style in config file (#85591) Specifying checks using the literal style (|) in the clang-tidy config file is currently supported but was not implemented for the --verify-config options. This means that clang-tidy would work properly but, using the --verify-config option would raise an error due to some checks not being parsed properly. Fixes #53737 --- clang-tools-extra/clang-tidy/GlobList.cpp | 14 +++-- clang-tools-extra/clang-tidy/GlobList.h | 4 ++ .../clang-tidy/tool/ClangTidyMain.cpp | 57 ++++++------------- clang-tools-extra/docs/ReleaseNotes.rst | 3 + .../infrastructure/verify-config.cpp | 12 ++++ 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/clang-tools-extra/clang-tidy/GlobList.cpp b/clang-tools-extra/clang-tidy/GlobList.cpp index dfe3f7c505b1..8f09ee075bbd 100644 --- a/clang-tools-extra/clang-tidy/GlobList.cpp +++ b/clang-tools-extra/clang-tidy/GlobList.cpp @@ -19,12 +19,17 @@ static bool consumeNegativeIndicator(StringRef &GlobList) { return GlobList.consume_front("-"); } -// Converts first glob from the comma-separated list of globs to Regex and -// removes it and the trailing comma from the GlobList. -static llvm::Regex consumeGlob(StringRef &GlobList) { +// Extracts the first glob from the comma-separated list of globs, +// removes it and the trailing comma from the GlobList and +// returns the extracted glob. +static llvm::StringRef extractNextGlob(StringRef &GlobList) { StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find_first_of(",\n")); StringRef Glob = UntrimmedGlob.trim(); GlobList = GlobList.substr(UntrimmedGlob.size() + 1); + return Glob; +} + +static llvm::Regex createRegexFromGlob(StringRef &Glob) { SmallString<128> RegexText("^"); StringRef MetaChars("()^$|*+?.[]\\{}"); for (char C : Glob) { @@ -43,7 +48,8 @@ GlobList::GlobList(StringRef Globs, bool KeepNegativeGlobs /* =true */) { do { GlobListItem Item; Item.IsPositive = !consumeNegativeIndicator(Globs); - Item.Regex = consumeGlob(Globs); + Item.Text = extractNextGlob(Globs); + Item.Regex = createRegexFromGlob(Item.Text); if (Item.IsPositive || KeepNegativeGlobs) Items.push_back(std::move(Item)); } while (!Globs.empty()); diff --git a/clang-tools-extra/clang-tidy/GlobList.h b/clang-tools-extra/clang-tidy/GlobList.h index 44af182e43b0..4317928270ad 100644 --- a/clang-tools-extra/clang-tidy/GlobList.h +++ b/clang-tools-extra/clang-tidy/GlobList.h @@ -44,8 +44,12 @@ private: struct GlobListItem { bool IsPositive; llvm::Regex Regex; + llvm::StringRef Text; }; SmallVector Items; + +public: + const SmallVectorImpl &getItems() const { return Items; }; }; /// A \p GlobList that caches search results, so that search is performed only diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index 9f3d6b6db6cb..f82f4417141d 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -454,52 +454,27 @@ static constexpr StringLiteral VerifyConfigWarningEnd = " [-verify-config]\n"; static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob, StringRef Source) { - llvm::StringRef Cur, Rest; + GlobList Globs(CheckGlob); bool AnyInvalid = false; - for (std::tie(Cur, Rest) = CheckGlob.split(','); - !(Cur.empty() && Rest.empty()); std::tie(Cur, Rest) = Rest.split(',')) { - Cur = Cur.trim(); - if (Cur.empty()) + for (const auto &Item : Globs.getItems()) { + if (Item.Text.starts_with("clang-diagnostic")) continue; - Cur.consume_front("-"); - if (Cur.starts_with("clang-diagnostic")) - continue; - if (Cur.contains('*')) { - SmallString<128> RegexText("^"); - StringRef MetaChars("()^$|*+?.[]\\{}"); - for (char C : Cur) { - if (C == '*') - RegexText.push_back('.'); - else if (MetaChars.contains(C)) - RegexText.push_back('\\'); - RegexText.push_back(C); - } - RegexText.push_back('$'); - llvm::Regex Glob(RegexText); - std::string Error; - if (!Glob.isValid(Error)) { - AnyInvalid = true; - llvm::WithColor::error(llvm::errs(), Source) - << "building check glob '" << Cur << "' " << Error << "'\n"; - continue; - } - if (llvm::none_of(AllChecks.keys(), - [&Glob](StringRef S) { return Glob.match(S); })) { - AnyInvalid = true; + if (llvm::none_of(AllChecks.keys(), + [&Item](StringRef S) { return Item.Regex.match(S); })) { + AnyInvalid = true; + if (Item.Text.contains('*')) llvm::WithColor::warning(llvm::errs(), Source) - << "check glob '" << Cur << "' doesn't match any known check" + << "check glob '" << Item.Text << "' doesn't match any known check" << VerifyConfigWarningEnd; + else { + llvm::raw_ostream &Output = + llvm::WithColor::warning(llvm::errs(), Source) + << "unknown check '" << Item.Text << '\''; + llvm::StringRef Closest = closest(Item.Text, AllChecks); + if (!Closest.empty()) + Output << "; did you mean '" << Closest << '\''; + Output << VerifyConfigWarningEnd; } - } else { - if (AllChecks.contains(Cur)) - continue; - AnyInvalid = true; - llvm::raw_ostream &Output = llvm::WithColor::warning(llvm::errs(), Source) - << "unknown check '" << Cur << '\''; - llvm::StringRef Closest = closest(Cur, AllChecks); - if (!Closest.empty()) - Output << "; did you mean '" << Closest << '\''; - Output << VerifyConfigWarningEnd; } } return AnyInvalid; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 9ef1d38d3c45..f3f9a81f9a8e 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -103,6 +103,9 @@ Improvements to clang-tidy - Improved :program:`check_clang_tidy.py` script. Added argument `-export-fixes` to aid in clang-tidy and test development. +- Fixed ``--verify-config`` option not properly parsing checks when using the + literal operator in the ``.clang-tidy`` config. + New checks ^^^^^^^^^^ diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp index 421f8641281a..365928598648 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/verify-config.cpp @@ -18,3 +18,15 @@ // CHECK-VERIFY: command-line option '-checks': warning: check glob 'bad*glob' doesn't match any known check [-verify-config] // CHECK-VERIFY: command-line option '-checks': warning: unknown check 'llvm-includeorder'; did you mean 'llvm-include-order' [-verify-config] // CHECK-VERIFY: command-line option '-checks': warning: unknown check 'my-made-up-check' [-verify-config] + +// RUN: echo -e 'Checks: |\n bugprone-argument-comment\n bugprone-assert-side-effect,\n bugprone-bool-pointer-implicit-conversion\n readability-use-anyof*' > %T/MyClangTidyConfig +// RUN: clang-tidy -verify-config \ +// RUN: --config-file=%T/MyClangTidyConfig | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-OK +// CHECK-VERIFY-BLOCK-OK: No config errors detected. + +// RUN: echo -e 'Checks: |\n bugprone-arguments-*\n bugprone-assert-side-effects\n bugprone-bool-pointer-implicit-conversion' > %T/MyClangTidyConfigBad +// RUN: not clang-tidy -verify-config \ +// RUN: --config-file=%T/MyClangTidyConfigBad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-BLOCK-BAD +// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: check glob 'bugprone-arguments-*' doesn't match any known check [-verify-config] +// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: unknown check 'bugprone-assert-side-effects'; did you mean 'bugprone-assert-side-effect' [-verify-config] + -- GitLab From 758d97dce0c669a0ba6927728b40030a76acb144 Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Tue, 23 Apr 2024 02:08:12 +0800 Subject: [PATCH 204/357] [MIPS]: Rework atomic max/min expand for subword (#89575) The current code is so buggy: it can work for few cases. The problems include: 1. ll/sc works on a whole word, while other parts other than we rmw are dropped. 2. The oprands are not well zero-extended for unsigned ops. 3. It doesn't work for big-endian, as the postion of subword differs with little endian. And in fact, we can set the return value correct in ll/sc scope, so we can skip the sinkMBB. --- llvm/lib/Target/Mips/MipsExpandPseudo.cpp | 114 +- llvm/test/CodeGen/Mips/atomic-min-max.ll | 1475 +++++++++++---------- 2 files changed, 823 insertions(+), 766 deletions(-) diff --git a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp index c30129743a96..d33852a04baf 100644 --- a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp @@ -342,6 +342,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( bool IsMin = false; bool IsMax = false; bool IsUnsigned = false; + bool DestOK = false; unsigned Opcode = 0; switch (I->getOpcode()) { @@ -388,6 +389,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( Opcode = Mips::XOR; break; case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA: + SEOp = Mips::SEB; IsUnsigned = true; IsMin = true; break; @@ -403,6 +405,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( IsMin = true; break; case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA: + SEOp = Mips::SEB; IsUnsigned = true; IsMax = true; break; @@ -473,48 +476,38 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ; unsigned MOVIncr = IsMax ? MOVN : MOVZ; - // For little endian we need to clear uninterested bits. - if (STI->isLittle()) { - if (!IsUnsigned) { - BuildMI(loopMBB, DL, TII->get(Mips::SRAV), OldVal) - .addReg(OldVal) - .addReg(ShiftAmnt); - BuildMI(loopMBB, DL, TII->get(Mips::SRAV), Incr) - .addReg(Incr) - .addReg(ShiftAmnt); - if (STI->hasMips32r2()) { - BuildMI(loopMBB, DL, TII->get(SEOp), OldVal).addReg(OldVal); - BuildMI(loopMBB, DL, TII->get(SEOp), Incr).addReg(Incr); - } else { - const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; - BuildMI(loopMBB, DL, TII->get(Mips::SLL), OldVal) - .addReg(OldVal, RegState::Kill) - .addImm(ShiftImm); - BuildMI(loopMBB, DL, TII->get(Mips::SRA), OldVal) - .addReg(OldVal, RegState::Kill) - .addImm(ShiftImm); - BuildMI(loopMBB, DL, TII->get(Mips::SLL), Incr) - .addReg(Incr, RegState::Kill) - .addImm(ShiftImm); - BuildMI(loopMBB, DL, TII->get(Mips::SRA), Incr) - .addReg(Incr, RegState::Kill) - .addImm(ShiftImm); - } - } else { - // and OldVal, OldVal, Mask - // and Incr, Incr, Mask - BuildMI(loopMBB, DL, TII->get(Mips::AND), OldVal) - .addReg(OldVal) - .addReg(Mask); - BuildMI(loopMBB, DL, TII->get(Mips::AND), Incr) - .addReg(Incr) - .addReg(Mask); - } + BuildMI(loopMBB, DL, TII->get(Mips::SRAV), StoreVal) + .addReg(OldVal) + .addReg(ShiftAmnt); + if (STI->hasMips32r2() && !IsUnsigned) { + BuildMI(loopMBB, DL, TII->get(SEOp), StoreVal).addReg(StoreVal); + } else if (STI->hasMips32r2() && IsUnsigned) { + const unsigned OpMask = SEOp == Mips::SEH ? 0xffff : 0xff; + BuildMI(loopMBB, DL, TII->get(Mips::ANDi), StoreVal) + .addReg(StoreVal) + .addImm(OpMask); + } else { + const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; + const unsigned SROp = IsUnsigned ? Mips::SRL : Mips::SRA; + BuildMI(loopMBB, DL, TII->get(Mips::SLL), StoreVal) + .addReg(StoreVal, RegState::Kill) + .addImm(ShiftImm); + BuildMI(loopMBB, DL, TII->get(SROp), StoreVal) + .addReg(StoreVal, RegState::Kill) + .addImm(ShiftImm); } - // unsigned: sltu Scratch4, oldVal, Incr - // signed: slt Scratch4, oldVal, Incr + BuildMI(loopMBB, DL, TII->get(Mips::OR), Dest) + .addReg(Mips::ZERO) + .addReg(StoreVal); + DestOK = true; + BuildMI(loopMBB, DL, TII->get(Mips::SLLV), StoreVal) + .addReg(StoreVal) + .addReg(ShiftAmnt); + + // unsigned: sltu Scratch4, StoreVal, Incr + // signed: slt Scratch4, StoreVal, Incr BuildMI(loopMBB, DL, TII->get(SLTScratch4), Scratch4) - .addReg(OldVal) + .addReg(StoreVal) .addReg(Incr); if (STI->hasMips64r6() || STI->hasMips32r6()) { @@ -525,7 +518,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( // seleqz Scratch4, Incr, Scratch4 // or BinOpRes, BinOpRes, Scratch4 BuildMI(loopMBB, DL, TII->get(SELOldVal), BinOpRes) - .addReg(OldVal) + .addReg(StoreVal) .addReg(Scratch4); BuildMI(loopMBB, DL, TII->get(SELIncr), Scratch4) .addReg(Incr) @@ -534,12 +527,12 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( .addReg(BinOpRes) .addReg(Scratch4); } else { - // max: move BinOpRes, OldVal + // max: move BinOpRes, StoreVal // movn BinOpRes, Incr, Scratch4, BinOpRes - // min: move BinOpRes, OldVal + // min: move BinOpRes, StoreVal // movz BinOpRes, Incr, Scratch4, BinOpRes BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) - .addReg(OldVal) + .addReg(StoreVal) .addReg(Mips::ZERO); BuildMI(loopMBB, DL, TII->get(MOVIncr), BinOpRes) .addReg(Incr) @@ -586,23 +579,24 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( // srl srlres,maskedoldval1,shiftamt // sign_extend dest,srlres - sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); - - BuildMI(sinkMBB, DL, TII->get(Mips::AND), Dest) - .addReg(OldVal).addReg(Mask); - BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest) - .addReg(Dest).addReg(ShiftAmnt); + if (!DestOK) { + sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); + BuildMI(sinkMBB, DL, TII->get(Mips::AND), Dest).addReg(OldVal).addReg(Mask); + BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest) + .addReg(Dest) + .addReg(ShiftAmnt); - if (STI->hasMips32r2()) { - BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); - } else { - const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; - BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest) - .addReg(Dest, RegState::Kill) - .addImm(ShiftImm); - BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest) - .addReg(Dest, RegState::Kill) - .addImm(ShiftImm); + if (STI->hasMips32r2()) { + BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); + } else { + const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; + BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest) + .addReg(Dest, RegState::Kill) + .addImm(ShiftImm); + BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest) + .addReg(Dest, RegState::Kill) + .addImm(ShiftImm); + } } LivePhysRegs LiveRegs; diff --git a/llvm/test/CodeGen/Mips/atomic-min-max.ll b/llvm/test/CodeGen/Mips/atomic-min-max.ll index a96581bdb39a..2f07d70808c1 100644 --- a/llvm/test/CodeGen/Mips/atomic-min-max.ll +++ b/llvm/test/CodeGen/Mips/atomic-min-max.ll @@ -912,8 +912,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: $BB4_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: slt $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: seh $4, $4 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: slt $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movn $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -922,9 +926,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: beqz $4, $BB4_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seh $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -952,8 +954,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: $BB4_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: slt $5, $2, $7 -; MIPSR6-NEXT: seleqz $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: seh $4, $4 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: slt $5, $4, $7 +; MIPSR6-NEXT: seleqz $3, $4, $5 ; MIPSR6-NEXT: selnez $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -961,10 +967,9 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB4_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seh $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -991,8 +996,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: $BB4_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: slt $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: seh $4, $4 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: slt $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movn $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -1000,9 +1009,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB4_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seh $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -1029,8 +1036,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: $BB4_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: slt $5, $2, $7 -; MMR6-NEXT: seleqz $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: seh $4, $4 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: slt $5, $4, $7 +; MMR6-NEXT: seleqz $3, $4, $5 ; MMR6-NEXT: selnez $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -1039,9 +1050,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB4_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seh $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -1067,14 +1076,13 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: $BB4_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: srav $2, $2, $10 -; MIPS32-NEXT: srav $7, $7, $10 -; MIPS32-NEXT: sll $2, $2, 16 -; MIPS32-NEXT: sra $2, $2, 16 -; MIPS32-NEXT: sll $7, $7, 16 -; MIPS32-NEXT: sra $7, $7, 16 -; MIPS32-NEXT: slt $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: sra $4, $4, 16 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: slt $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movn $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -1083,10 +1091,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: beqz $4, $BB4_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $1, $1, 16 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -1095,7 +1100,6 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: addiu $sp, $sp, 8 ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: nop - ; ; MIPSEL-LABEL: test_max_16: ; MIPSEL: # %bb.0: # %entry @@ -1114,12 +1118,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: $BB4_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: srav $2, $2, $10 -; MIPSEL-NEXT: srav $7, $7, $10 -; MIPSEL-NEXT: seh $2, $2 -; MIPSEL-NEXT: seh $7, $7 -; MIPSEL-NEXT: slt $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: seh $4, $4 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: slt $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movn $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -1128,9 +1132,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB4_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seh $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -1157,12 +1159,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: $BB4_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: srav $2, $2, $10 -; MIPSELR6-NEXT: srav $7, $7, $10 -; MIPSELR6-NEXT: seh $2, $2 -; MIPSELR6-NEXT: seh $7, $7 -; MIPSELR6-NEXT: slt $5, $2, $7 -; MIPSELR6-NEXT: seleqz $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: seh $4, $4 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: slt $5, $4, $7 +; MIPSELR6-NEXT: seleqz $3, $4, $5 ; MIPSELR6-NEXT: selnez $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -1170,10 +1172,9 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB4_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seh $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -1199,12 +1200,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: $BB4_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: srav $2, $2, $10 -; MMEL-NEXT: srav $7, $7, $10 -; MMEL-NEXT: seh $2, $2 -; MMEL-NEXT: seh $7, $7 -; MMEL-NEXT: slt $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: seh $4, $4 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: slt $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movn $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -1212,9 +1213,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB4_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seh $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -1240,12 +1239,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: $BB4_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: srav $2, $2, $10 -; MMELR6-NEXT: srav $7, $7, $10 -; MMELR6-NEXT: seh $2, $2 -; MMELR6-NEXT: seh $7, $7 -; MMELR6-NEXT: slt $5, $2, $7 -; MMELR6-NEXT: seleqz $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: seh $4, $4 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: slt $5, $4, $7 +; MMELR6-NEXT: seleqz $3, $4, $5 ; MMELR6-NEXT: selnez $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -1254,9 +1253,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB4_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seh $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -1283,8 +1280,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: .LBB4_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: slt $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: seh $4, $4 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: slt $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movn $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -1293,9 +1294,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB4_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seh $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -1323,8 +1322,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: .LBB4_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: slt $5, $2, $7 -; MIPS64R6-NEXT: seleqz $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: seh $4, $4 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: slt $5, $4, $7 +; MIPS64R6-NEXT: seleqz $3, $4, $5 ; MIPS64R6-NEXT: selnez $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -1332,10 +1335,9 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB4_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seh $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -1361,12 +1363,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: .LBB4_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: srav $2, $2, $10 -; MIPS64EL-NEXT: srav $7, $7, $10 -; MIPS64EL-NEXT: seh $2, $2 -; MIPS64EL-NEXT: seh $7, $7 -; MIPS64EL-NEXT: slt $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: seh $4, $4 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: slt $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movn $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -1375,9 +1377,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB4_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seh $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -1404,12 +1404,12 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: .LBB4_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: srav $2, $2, $10 -; MIPS64ELR6-NEXT: srav $7, $7, $10 -; MIPS64ELR6-NEXT: seh $2, $2 -; MIPS64ELR6-NEXT: seh $7, $7 -; MIPS64ELR6-NEXT: slt $5, $2, $7 -; MIPS64ELR6-NEXT: seleqz $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: seh $4, $4 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: slt $5, $4, $7 +; MIPS64ELR6-NEXT: seleqz $3, $4, $5 ; MIPS64ELR6-NEXT: selnez $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -1417,10 +1417,9 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB4_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seh $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -1428,6 +1427,7 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: sync ; MIPS64ELR6-NEXT: daddiu $sp, $sp, 16 ; MIPS64ELR6-NEXT: jrc $ra + entry: %0 = atomicrmw max ptr %ptr, i16 %val seq_cst ret i16 %0 @@ -1452,8 +1452,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: $BB5_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: slt $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: seh $4, $4 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: slt $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movz $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -1462,9 +1466,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: beqz $4, $BB5_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seh $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -1492,8 +1494,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: $BB5_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: slt $5, $2, $7 -; MIPSR6-NEXT: selnez $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: seh $4, $4 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: slt $5, $4, $7 +; MIPSR6-NEXT: selnez $3, $4, $5 ; MIPSR6-NEXT: seleqz $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -1501,10 +1507,9 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB5_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seh $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -1531,8 +1536,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: $BB5_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: slt $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: seh $4, $4 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: slt $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movz $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -1540,9 +1549,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB5_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seh $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -1569,8 +1576,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: $BB5_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: slt $5, $2, $7 -; MMR6-NEXT: selnez $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: seh $4, $4 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: slt $5, $4, $7 +; MMR6-NEXT: selnez $3, $4, $5 ; MMR6-NEXT: seleqz $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -1579,9 +1590,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB5_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seh $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -1607,14 +1616,13 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: $BB5_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: srav $2, $2, $10 -; MIPS32-NEXT: srav $7, $7, $10 -; MIPS32-NEXT: sll $2, $2, 16 -; MIPS32-NEXT: sra $2, $2, 16 -; MIPS32-NEXT: sll $7, $7, 16 -; MIPS32-NEXT: sra $7, $7, 16 -; MIPS32-NEXT: slt $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: sra $4, $4, 16 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: slt $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movz $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -1623,10 +1631,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: beqz $4, $BB5_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $1, $1, 16 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -1653,12 +1658,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: $BB5_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: srav $2, $2, $10 -; MIPSEL-NEXT: srav $7, $7, $10 -; MIPSEL-NEXT: seh $2, $2 -; MIPSEL-NEXT: seh $7, $7 -; MIPSEL-NEXT: slt $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: seh $4, $4 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: slt $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movz $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -1667,9 +1672,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB5_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seh $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -1696,12 +1699,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: $BB5_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: srav $2, $2, $10 -; MIPSELR6-NEXT: srav $7, $7, $10 -; MIPSELR6-NEXT: seh $2, $2 -; MIPSELR6-NEXT: seh $7, $7 -; MIPSELR6-NEXT: slt $5, $2, $7 -; MIPSELR6-NEXT: selnez $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: seh $4, $4 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: slt $5, $4, $7 +; MIPSELR6-NEXT: selnez $3, $4, $5 ; MIPSELR6-NEXT: seleqz $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -1709,10 +1712,9 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB5_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seh $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -1738,12 +1740,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: $BB5_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: srav $2, $2, $10 -; MMEL-NEXT: srav $7, $7, $10 -; MMEL-NEXT: seh $2, $2 -; MMEL-NEXT: seh $7, $7 -; MMEL-NEXT: slt $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: seh $4, $4 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: slt $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movz $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -1751,9 +1753,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB5_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seh $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -1779,12 +1779,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: $BB5_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: srav $2, $2, $10 -; MMELR6-NEXT: srav $7, $7, $10 -; MMELR6-NEXT: seh $2, $2 -; MMELR6-NEXT: seh $7, $7 -; MMELR6-NEXT: slt $5, $2, $7 -; MMELR6-NEXT: selnez $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: seh $4, $4 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: slt $5, $4, $7 +; MMELR6-NEXT: selnez $3, $4, $5 ; MMELR6-NEXT: seleqz $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -1793,9 +1793,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB5_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seh $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -1822,8 +1820,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: .LBB5_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: slt $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: seh $4, $4 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: slt $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movz $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -1832,9 +1834,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB5_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seh $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -1862,8 +1862,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: .LBB5_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: slt $5, $2, $7 -; MIPS64R6-NEXT: selnez $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: seh $4, $4 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: slt $5, $4, $7 +; MIPS64R6-NEXT: selnez $3, $4, $5 ; MIPS64R6-NEXT: seleqz $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -1871,10 +1875,9 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB5_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seh $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -1900,12 +1903,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: .LBB5_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: srav $2, $2, $10 -; MIPS64EL-NEXT: srav $7, $7, $10 -; MIPS64EL-NEXT: seh $2, $2 -; MIPS64EL-NEXT: seh $7, $7 -; MIPS64EL-NEXT: slt $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: seh $4, $4 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: slt $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movz $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -1914,9 +1917,7 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB5_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seh $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -1943,12 +1944,12 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: .LBB5_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: srav $2, $2, $10 -; MIPS64ELR6-NEXT: srav $7, $7, $10 -; MIPS64ELR6-NEXT: seh $2, $2 -; MIPS64ELR6-NEXT: seh $7, $7 -; MIPS64ELR6-NEXT: slt $5, $2, $7 -; MIPS64ELR6-NEXT: selnez $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: seh $4, $4 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: slt $5, $4, $7 +; MIPS64ELR6-NEXT: selnez $3, $4, $5 ; MIPS64ELR6-NEXT: seleqz $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -1956,10 +1957,9 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB5_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seh $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -1991,8 +1991,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: $BB6_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: sltu $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: andi $4, $4, 65535 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: sltu $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movn $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -2001,9 +2005,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: beqz $4, $BB6_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seh $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -2031,8 +2033,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: $BB6_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: sltu $5, $2, $7 -; MIPSR6-NEXT: seleqz $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: andi $4, $4, 65535 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: sltu $5, $4, $7 +; MIPSR6-NEXT: seleqz $3, $4, $5 ; MIPSR6-NEXT: selnez $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -2040,10 +2046,9 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB6_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seh $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -2070,8 +2075,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: $BB6_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: sltu $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: andi $4, $4, 65535 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: sltu $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movn $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -2079,9 +2088,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB6_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seh $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -2108,8 +2115,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: $BB6_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: sltu $5, $2, $7 -; MMR6-NEXT: seleqz $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: andi $4, $4, 65535 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: sltu $5, $4, $7 +; MMR6-NEXT: seleqz $3, $4, $5 ; MMR6-NEXT: selnez $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -2118,9 +2129,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB6_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seh $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -2146,10 +2155,13 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: $BB6_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: and $2, $2, $8 -; MIPS32-NEXT: and $7, $7, $8 -; MIPS32-NEXT: sltu $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: srl $4, $4, 16 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: sltu $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movn $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -2158,10 +2170,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: beqz $4, $BB6_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $1, $1, 16 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -2188,10 +2197,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: $BB6_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: and $2, $2, $8 -; MIPSEL-NEXT: and $7, $7, $8 -; MIPSEL-NEXT: sltu $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: andi $4, $4, 65535 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: sltu $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movn $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -2200,9 +2211,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB6_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seh $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -2229,10 +2238,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: $BB6_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: and $2, $2, $8 -; MIPSELR6-NEXT: and $7, $7, $8 -; MIPSELR6-NEXT: sltu $5, $2, $7 -; MIPSELR6-NEXT: seleqz $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: andi $4, $4, 65535 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: sltu $5, $4, $7 +; MIPSELR6-NEXT: seleqz $3, $4, $5 ; MIPSELR6-NEXT: selnez $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -2240,10 +2251,9 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB6_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seh $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -2269,10 +2279,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: $BB6_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: and $2, $2, $8 -; MMEL-NEXT: and $7, $7, $8 -; MMEL-NEXT: sltu $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: andi $4, $4, 65535 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: sltu $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movn $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -2280,9 +2292,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB6_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seh $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -2308,10 +2318,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: $BB6_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: and $2, $2, $8 -; MMELR6-NEXT: and $7, $7, $8 -; MMELR6-NEXT: sltu $5, $2, $7 -; MMELR6-NEXT: seleqz $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: andi $4, $4, 65535 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: sltu $5, $4, $7 +; MMELR6-NEXT: seleqz $3, $4, $5 ; MMELR6-NEXT: selnez $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -2320,9 +2332,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB6_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seh $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -2349,8 +2359,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: .LBB6_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: sltu $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: andi $4, $4, 65535 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: sltu $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movn $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -2359,9 +2373,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB6_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seh $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -2389,8 +2401,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: .LBB6_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: sltu $5, $2, $7 -; MIPS64R6-NEXT: seleqz $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: andi $4, $4, 65535 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: sltu $5, $4, $7 +; MIPS64R6-NEXT: seleqz $3, $4, $5 ; MIPS64R6-NEXT: selnez $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -2398,10 +2414,9 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB6_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seh $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -2427,10 +2442,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: .LBB6_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: and $2, $2, $8 -; MIPS64EL-NEXT: and $7, $7, $8 -; MIPS64EL-NEXT: sltu $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: andi $4, $4, 65535 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: sltu $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movn $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -2439,9 +2456,7 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB6_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seh $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -2468,10 +2483,12 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: .LBB6_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: and $2, $2, $8 -; MIPS64ELR6-NEXT: and $7, $7, $8 -; MIPS64ELR6-NEXT: sltu $5, $2, $7 -; MIPS64ELR6-NEXT: seleqz $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: andi $4, $4, 65535 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: sltu $5, $4, $7 +; MIPS64ELR6-NEXT: seleqz $3, $4, $5 ; MIPS64ELR6-NEXT: selnez $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -2479,10 +2496,9 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB6_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seh $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -2514,8 +2530,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: $BB7_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: sltu $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: andi $4, $4, 65535 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: sltu $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movz $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -2524,9 +2544,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: beqz $4, $BB7_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seh $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -2554,8 +2572,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: $BB7_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: sltu $5, $2, $7 -; MIPSR6-NEXT: selnez $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: andi $4, $4, 65535 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: sltu $5, $4, $7 +; MIPSR6-NEXT: selnez $3, $4, $5 ; MIPSR6-NEXT: seleqz $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -2563,10 +2585,9 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB7_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seh $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -2593,8 +2614,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: $BB7_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: sltu $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: andi $4, $4, 65535 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: sltu $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movz $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -2602,9 +2627,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB7_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seh $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -2631,8 +2654,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: $BB7_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: sltu $5, $2, $7 -; MMR6-NEXT: selnez $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: andi $4, $4, 65535 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: sltu $5, $4, $7 +; MMR6-NEXT: selnez $3, $4, $5 ; MMR6-NEXT: seleqz $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -2641,9 +2668,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB7_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seh $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -2669,10 +2694,13 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: $BB7_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: and $2, $2, $8 -; MIPS32-NEXT: and $7, $7, $8 -; MIPS32-NEXT: sltu $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 16 +; MIPS32-NEXT: srl $4, $4, 16 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: sltu $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movz $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -2681,10 +2709,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: beqz $4, $BB7_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $1, $1, 16 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -2694,7 +2719,6 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: nop ; -; ; MIPSEL-LABEL: test_umin_16: ; MIPSEL: # %bb.0: # %entry ; MIPSEL-NEXT: addiu $sp, $sp, -8 @@ -2712,10 +2736,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: $BB7_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: and $2, $2, $8 -; MIPSEL-NEXT: and $7, $7, $8 -; MIPSEL-NEXT: sltu $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: andi $4, $4, 65535 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: sltu $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movz $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -2724,9 +2750,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB7_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seh $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -2753,10 +2777,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: $BB7_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: and $2, $2, $8 -; MIPSELR6-NEXT: and $7, $7, $8 -; MIPSELR6-NEXT: sltu $5, $2, $7 -; MIPSELR6-NEXT: selnez $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: andi $4, $4, 65535 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: sltu $5, $4, $7 +; MIPSELR6-NEXT: selnez $3, $4, $5 ; MIPSELR6-NEXT: seleqz $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -2764,10 +2790,9 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB7_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seh $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -2793,10 +2818,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: $BB7_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: and $2, $2, $8 -; MMEL-NEXT: and $7, $7, $8 -; MMEL-NEXT: sltu $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: andi $4, $4, 65535 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: sltu $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movz $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -2804,9 +2831,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB7_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seh $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -2832,10 +2857,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: $BB7_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: and $2, $2, $8 -; MMELR6-NEXT: and $7, $7, $8 -; MMELR6-NEXT: sltu $5, $2, $7 -; MMELR6-NEXT: selnez $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: andi $4, $4, 65535 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: sltu $5, $4, $7 +; MMELR6-NEXT: selnez $3, $4, $5 ; MMELR6-NEXT: seleqz $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -2844,9 +2871,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB7_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seh $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -2873,8 +2898,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: .LBB7_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: sltu $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: andi $4, $4, 65535 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: sltu $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movz $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -2883,9 +2912,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB7_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seh $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -2913,8 +2940,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: .LBB7_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: sltu $5, $2, $7 -; MIPS64R6-NEXT: selnez $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: andi $4, $4, 65535 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: sltu $5, $4, $7 +; MIPS64R6-NEXT: selnez $3, $4, $5 ; MIPS64R6-NEXT: seleqz $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -2922,10 +2953,9 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB7_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seh $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -2951,10 +2981,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: .LBB7_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: and $2, $2, $8 -; MIPS64EL-NEXT: and $7, $7, $8 -; MIPS64EL-NEXT: sltu $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: andi $4, $4, 65535 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: sltu $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movz $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -2963,9 +2995,7 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB7_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seh $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -2992,10 +3022,12 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: .LBB7_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: and $2, $2, $8 -; MIPS64ELR6-NEXT: and $7, $7, $8 -; MIPS64ELR6-NEXT: sltu $5, $2, $7 -; MIPS64ELR6-NEXT: selnez $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: andi $4, $4, 65535 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: sltu $5, $4, $7 +; MIPS64ELR6-NEXT: selnez $3, $4, $5 ; MIPS64ELR6-NEXT: seleqz $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -3003,10 +3035,9 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB7_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seh $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -3039,8 +3070,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: $BB8_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: slt $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: seb $4, $4 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: slt $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movn $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -3049,9 +3084,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: beqz $4, $BB8_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seb $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -3079,8 +3112,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: $BB8_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: slt $5, $2, $7 -; MIPSR6-NEXT: seleqz $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: seb $4, $4 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: slt $5, $4, $7 +; MIPSR6-NEXT: seleqz $3, $4, $5 ; MIPSR6-NEXT: selnez $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -3088,10 +3125,9 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB8_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seb $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -3118,8 +3154,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: $BB8_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: slt $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: seb $4, $4 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: slt $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movn $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -3127,9 +3167,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB8_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seb $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -3156,8 +3194,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: $BB8_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: slt $5, $2, $7 -; MMR6-NEXT: seleqz $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: seb $4, $4 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: slt $5, $4, $7 +; MMR6-NEXT: seleqz $3, $4, $5 ; MMR6-NEXT: selnez $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -3166,9 +3208,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB8_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seb $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -3194,14 +3234,13 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: $BB8_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: srav $2, $2, $10 -; MIPS32-NEXT: srav $7, $7, $10 -; MIPS32-NEXT: sll $2, $2, 24 -; MIPS32-NEXT: sra $2, $2, 24 -; MIPS32-NEXT: sll $7, $7, 24 -; MIPS32-NEXT: sra $7, $7, 24 -; MIPS32-NEXT: slt $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: sra $4, $4, 24 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: slt $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movn $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -3210,10 +3249,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: beqz $4, $BB8_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 24 -; MIPS32-NEXT: sra $1, $1, 24 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -3240,12 +3276,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: $BB8_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: srav $2, $2, $10 -; MIPSEL-NEXT: srav $7, $7, $10 -; MIPSEL-NEXT: seb $2, $2 -; MIPSEL-NEXT: seb $7, $7 -; MIPSEL-NEXT: slt $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: seb $4, $4 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: slt $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movn $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -3254,9 +3290,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB8_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seb $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -3283,12 +3317,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: $BB8_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: srav $2, $2, $10 -; MIPSELR6-NEXT: srav $7, $7, $10 -; MIPSELR6-NEXT: seb $2, $2 -; MIPSELR6-NEXT: seb $7, $7 -; MIPSELR6-NEXT: slt $5, $2, $7 -; MIPSELR6-NEXT: seleqz $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: seb $4, $4 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: slt $5, $4, $7 +; MIPSELR6-NEXT: seleqz $3, $4, $5 ; MIPSELR6-NEXT: selnez $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -3296,10 +3330,9 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB8_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seb $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -3325,12 +3358,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: $BB8_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: srav $2, $2, $10 -; MMEL-NEXT: srav $7, $7, $10 -; MMEL-NEXT: seb $2, $2 -; MMEL-NEXT: seb $7, $7 -; MMEL-NEXT: slt $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: seb $4, $4 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: slt $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movn $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -3338,9 +3371,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB8_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seb $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -3366,12 +3397,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: $BB8_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: srav $2, $2, $10 -; MMELR6-NEXT: srav $7, $7, $10 -; MMELR6-NEXT: seb $2, $2 -; MMELR6-NEXT: seb $7, $7 -; MMELR6-NEXT: slt $5, $2, $7 -; MMELR6-NEXT: seleqz $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: seb $4, $4 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: slt $5, $4, $7 +; MMELR6-NEXT: seleqz $3, $4, $5 ; MMELR6-NEXT: selnez $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -3380,9 +3411,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB8_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seb $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -3409,8 +3438,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: .LBB8_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: slt $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: seb $4, $4 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: slt $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movn $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -3419,9 +3452,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB8_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seb $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -3449,8 +3480,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: .LBB8_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: slt $5, $2, $7 -; MIPS64R6-NEXT: seleqz $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: seb $4, $4 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: slt $5, $4, $7 +; MIPS64R6-NEXT: seleqz $3, $4, $5 ; MIPS64R6-NEXT: selnez $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -3458,10 +3493,9 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB8_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seb $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -3487,12 +3521,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: .LBB8_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: srav $2, $2, $10 -; MIPS64EL-NEXT: srav $7, $7, $10 -; MIPS64EL-NEXT: seb $2, $2 -; MIPS64EL-NEXT: seb $7, $7 -; MIPS64EL-NEXT: slt $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: seb $4, $4 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: slt $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movn $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -3501,9 +3535,7 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB8_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seb $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -3530,12 +3562,12 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: .LBB8_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: srav $2, $2, $10 -; MIPS64ELR6-NEXT: srav $7, $7, $10 -; MIPS64ELR6-NEXT: seb $2, $2 -; MIPS64ELR6-NEXT: seb $7, $7 -; MIPS64ELR6-NEXT: slt $5, $2, $7 -; MIPS64ELR6-NEXT: seleqz $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: seb $4, $4 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: slt $5, $4, $7 +; MIPS64ELR6-NEXT: seleqz $3, $4, $5 ; MIPS64ELR6-NEXT: selnez $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -3543,10 +3575,9 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB8_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seb $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -3578,8 +3609,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: $BB9_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: slt $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: seb $4, $4 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: slt $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movz $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -3588,9 +3623,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: beqz $4, $BB9_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seb $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -3618,8 +3651,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: $BB9_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: slt $5, $2, $7 -; MIPSR6-NEXT: selnez $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: seb $4, $4 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: slt $5, $4, $7 +; MIPSR6-NEXT: selnez $3, $4, $5 ; MIPSR6-NEXT: seleqz $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -3627,10 +3664,9 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB9_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seb $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -3657,8 +3693,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: $BB9_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: slt $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: seb $4, $4 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: slt $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movz $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -3666,9 +3706,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB9_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seb $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -3695,8 +3733,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: $BB9_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: slt $5, $2, $7 -; MMR6-NEXT: selnez $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: seb $4, $4 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: slt $5, $4, $7 +; MMR6-NEXT: selnez $3, $4, $5 ; MMR6-NEXT: seleqz $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -3705,9 +3747,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB9_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seb $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -3733,14 +3773,13 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: $BB9_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: srav $2, $2, $10 -; MIPS32-NEXT: srav $7, $7, $10 -; MIPS32-NEXT: sll $2, $2, 24 -; MIPS32-NEXT: sra $2, $2, 24 -; MIPS32-NEXT: sll $7, $7, 24 -; MIPS32-NEXT: sra $7, $7, 24 -; MIPS32-NEXT: slt $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: sra $4, $4, 24 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: slt $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movz $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -3749,10 +3788,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: beqz $4, $BB9_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 24 -; MIPS32-NEXT: sra $1, $1, 24 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -3779,12 +3815,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: $BB9_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: srav $2, $2, $10 -; MIPSEL-NEXT: srav $7, $7, $10 -; MIPSEL-NEXT: seb $2, $2 -; MIPSEL-NEXT: seb $7, $7 -; MIPSEL-NEXT: slt $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: seb $4, $4 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: slt $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movz $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -3793,9 +3829,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB9_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seb $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -3822,12 +3856,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: $BB9_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: srav $2, $2, $10 -; MIPSELR6-NEXT: srav $7, $7, $10 -; MIPSELR6-NEXT: seb $2, $2 -; MIPSELR6-NEXT: seb $7, $7 -; MIPSELR6-NEXT: slt $5, $2, $7 -; MIPSELR6-NEXT: selnez $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: seb $4, $4 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: slt $5, $4, $7 +; MIPSELR6-NEXT: selnez $3, $4, $5 ; MIPSELR6-NEXT: seleqz $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -3835,10 +3869,9 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB9_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seb $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -3864,12 +3897,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: $BB9_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: srav $2, $2, $10 -; MMEL-NEXT: srav $7, $7, $10 -; MMEL-NEXT: seb $2, $2 -; MMEL-NEXT: seb $7, $7 -; MMEL-NEXT: slt $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: seb $4, $4 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: slt $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movz $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -3877,9 +3910,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB9_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seb $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -3905,12 +3936,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: $BB9_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: srav $2, $2, $10 -; MMELR6-NEXT: srav $7, $7, $10 -; MMELR6-NEXT: seb $2, $2 -; MMELR6-NEXT: seb $7, $7 -; MMELR6-NEXT: slt $5, $2, $7 -; MMELR6-NEXT: selnez $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: seb $4, $4 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: slt $5, $4, $7 +; MMELR6-NEXT: selnez $3, $4, $5 ; MMELR6-NEXT: seleqz $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -3919,9 +3950,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB9_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seb $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -3948,8 +3977,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: .LBB9_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: slt $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: seb $4, $4 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: slt $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movz $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -3958,9 +3991,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB9_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seb $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -3988,8 +4019,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: .LBB9_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: slt $5, $2, $7 -; MIPS64R6-NEXT: selnez $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: seb $4, $4 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: slt $5, $4, $7 +; MIPS64R6-NEXT: selnez $3, $4, $5 ; MIPS64R6-NEXT: seleqz $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -3997,10 +4032,9 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB9_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seb $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -4026,12 +4060,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: .LBB9_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: srav $2, $2, $10 -; MIPS64EL-NEXT: srav $7, $7, $10 -; MIPS64EL-NEXT: seb $2, $2 -; MIPS64EL-NEXT: seb $7, $7 -; MIPS64EL-NEXT: slt $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: seb $4, $4 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: slt $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movz $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -4040,9 +4074,7 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB9_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seb $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -4069,12 +4101,12 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: .LBB9_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: srav $2, $2, $10 -; MIPS64ELR6-NEXT: srav $7, $7, $10 -; MIPS64ELR6-NEXT: seb $2, $2 -; MIPS64ELR6-NEXT: seb $7, $7 -; MIPS64ELR6-NEXT: slt $5, $2, $7 -; MIPS64ELR6-NEXT: selnez $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: seb $4, $4 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: slt $5, $4, $7 +; MIPS64ELR6-NEXT: selnez $3, $4, $5 ; MIPS64ELR6-NEXT: seleqz $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -4082,10 +4114,9 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB9_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seb $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -4117,8 +4148,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: $BB10_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: sltu $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: andi $4, $4, 255 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: sltu $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movn $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -4127,9 +4162,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: beqz $4, $BB10_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seh $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -4157,8 +4190,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: $BB10_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: sltu $5, $2, $7 -; MIPSR6-NEXT: seleqz $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: andi $4, $4, 255 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: sltu $5, $4, $7 +; MIPSR6-NEXT: seleqz $3, $4, $5 ; MIPSR6-NEXT: selnez $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -4166,10 +4203,9 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB10_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seh $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -4196,8 +4232,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: $BB10_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: sltu $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: andi $4, $4, 255 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: sltu $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movn $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -4205,9 +4245,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB10_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seh $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -4234,8 +4272,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: $BB10_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: sltu $5, $2, $7 -; MMR6-NEXT: seleqz $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: andi $4, $4, 255 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: sltu $5, $4, $7 +; MMR6-NEXT: seleqz $3, $4, $5 ; MMR6-NEXT: selnez $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -4244,9 +4286,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB10_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seh $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -4272,10 +4312,13 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: $BB10_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: and $2, $2, $8 -; MIPS32-NEXT: and $7, $7, $8 -; MIPS32-NEXT: sltu $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: srl $4, $4, 24 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: sltu $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movn $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -4284,10 +4327,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: beqz $4, $BB10_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $1, $1, 16 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -4314,10 +4354,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: $BB10_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: and $2, $2, $8 -; MIPSEL-NEXT: and $7, $7, $8 -; MIPSEL-NEXT: sltu $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: andi $4, $4, 255 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: sltu $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movn $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -4326,9 +4368,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB10_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seh $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -4355,10 +4395,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: $BB10_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: and $2, $2, $8 -; MIPSELR6-NEXT: and $7, $7, $8 -; MIPSELR6-NEXT: sltu $5, $2, $7 -; MIPSELR6-NEXT: seleqz $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: andi $4, $4, 255 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: sltu $5, $4, $7 +; MIPSELR6-NEXT: seleqz $3, $4, $5 ; MIPSELR6-NEXT: selnez $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -4366,10 +4408,9 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB10_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seh $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -4395,10 +4436,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: $BB10_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: and $2, $2, $8 -; MMEL-NEXT: and $7, $7, $8 -; MMEL-NEXT: sltu $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: andi $4, $4, 255 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: sltu $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movn $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -4406,9 +4449,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB10_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seh $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -4434,10 +4475,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: $BB10_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: and $2, $2, $8 -; MMELR6-NEXT: and $7, $7, $8 -; MMELR6-NEXT: sltu $5, $2, $7 -; MMELR6-NEXT: seleqz $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: andi $4, $4, 255 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: sltu $5, $4, $7 +; MMELR6-NEXT: seleqz $3, $4, $5 ; MMELR6-NEXT: selnez $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -4446,9 +4489,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB10_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seh $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -4475,8 +4516,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: .LBB10_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: sltu $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: andi $4, $4, 255 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: sltu $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movn $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -4485,9 +4530,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB10_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seh $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -4515,8 +4558,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: .LBB10_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: sltu $5, $2, $7 -; MIPS64R6-NEXT: seleqz $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: andi $4, $4, 255 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: sltu $5, $4, $7 +; MIPS64R6-NEXT: seleqz $3, $4, $5 ; MIPS64R6-NEXT: selnez $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -4524,10 +4571,9 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB10_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seh $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -4553,10 +4599,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: .LBB10_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: and $2, $2, $8 -; MIPS64EL-NEXT: and $7, $7, $8 -; MIPS64EL-NEXT: sltu $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: andi $4, $4, 255 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: sltu $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movn $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -4565,9 +4613,7 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB10_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seh $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -4594,10 +4640,12 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: .LBB10_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: and $2, $2, $8 -; MIPS64ELR6-NEXT: and $7, $7, $8 -; MIPS64ELR6-NEXT: sltu $5, $2, $7 -; MIPS64ELR6-NEXT: seleqz $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: andi $4, $4, 255 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: sltu $5, $4, $7 +; MIPS64ELR6-NEXT: seleqz $3, $4, $5 ; MIPS64ELR6-NEXT: selnez $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -4605,10 +4653,9 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB10_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seh $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry @@ -4640,8 +4687,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: $BB11_1: # %entry ; MIPS-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS-NEXT: ll $2, 0($6) -; MIPS-NEXT: sltu $5, $2, $7 -; MIPS-NEXT: move $3, $2 +; MIPS-NEXT: srav $4, $2, $10 +; MIPS-NEXT: andi $4, $4, 255 +; MIPS-NEXT: or $1, $zero, $4 +; MIPS-NEXT: sllv $4, $4, $10 +; MIPS-NEXT: sltu $5, $4, $7 +; MIPS-NEXT: move $3, $4 ; MIPS-NEXT: movz $3, $7, $5 ; MIPS-NEXT: and $3, $3, $8 ; MIPS-NEXT: and $4, $2, $9 @@ -4650,9 +4701,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: beqz $4, $BB11_1 ; MIPS-NEXT: nop ; MIPS-NEXT: # %bb.2: # %entry -; MIPS-NEXT: and $1, $2, $8 -; MIPS-NEXT: srlv $1, $1, $10 -; MIPS-NEXT: seh $1, $1 +; MIPS-NEXT: .insn ; MIPS-NEXT: # %bb.3: # %entry ; MIPS-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS-NEXT: # %bb.4: # %entry @@ -4680,8 +4729,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: $BB11_1: # %entry ; MIPSR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSR6-NEXT: ll $2, 0($6) -; MIPSR6-NEXT: sltu $5, $2, $7 -; MIPSR6-NEXT: selnez $3, $2, $5 +; MIPSR6-NEXT: srav $4, $2, $10 +; MIPSR6-NEXT: andi $4, $4, 255 +; MIPSR6-NEXT: or $1, $zero, $4 +; MIPSR6-NEXT: sllv $4, $4, $10 +; MIPSR6-NEXT: sltu $5, $4, $7 +; MIPSR6-NEXT: selnez $3, $4, $5 ; MIPSR6-NEXT: seleqz $5, $7, $5 ; MIPSR6-NEXT: or $3, $3, $5 ; MIPSR6-NEXT: and $3, $3, $8 @@ -4689,10 +4742,9 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSR6-NEXT: or $4, $4, $3 ; MIPSR6-NEXT: sc $4, 0($6) ; MIPSR6-NEXT: beqzc $4, $BB11_1 +; MIPSR6-NEXT: nop ; MIPSR6-NEXT: # %bb.2: # %entry -; MIPSR6-NEXT: and $1, $2, $8 -; MIPSR6-NEXT: srlv $1, $1, $10 -; MIPSR6-NEXT: seh $1, $1 +; MIPSR6-NEXT: .insn ; MIPSR6-NEXT: # %bb.3: # %entry ; MIPSR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSR6-NEXT: # %bb.4: # %entry @@ -4719,8 +4771,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: $BB11_1: # %entry ; MM-NEXT: # =>This Inner Loop Header: Depth=1 ; MM-NEXT: ll $2, 0($6) -; MM-NEXT: sltu $5, $2, $7 -; MM-NEXT: or $3, $2, $zero +; MM-NEXT: srav $4, $2, $10 +; MM-NEXT: andi $4, $4, 255 +; MM-NEXT: or $1, $zero, $4 +; MM-NEXT: sllv $4, $4, $10 +; MM-NEXT: sltu $5, $4, $7 +; MM-NEXT: or $3, $4, $zero ; MM-NEXT: movz $3, $7, $5 ; MM-NEXT: and $3, $3, $8 ; MM-NEXT: and $4, $2, $9 @@ -4728,9 +4784,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MM-NEXT: sc $4, 0($6) ; MM-NEXT: beqzc $4, $BB11_1 ; MM-NEXT: # %bb.2: # %entry -; MM-NEXT: and $1, $2, $8 -; MM-NEXT: srlv $1, $1, $10 -; MM-NEXT: seh $1, $1 +; MM-NEXT: .insn ; MM-NEXT: # %bb.3: # %entry ; MM-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MM-NEXT: # %bb.4: # %entry @@ -4757,8 +4811,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: $BB11_1: # %entry ; MMR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMR6-NEXT: ll $2, 0($6) -; MMR6-NEXT: sltu $5, $2, $7 -; MMR6-NEXT: selnez $3, $2, $5 +; MMR6-NEXT: srav $4, $2, $10 +; MMR6-NEXT: andi $4, $4, 255 +; MMR6-NEXT: or $1, $zero, $4 +; MMR6-NEXT: sllv $4, $4, $10 +; MMR6-NEXT: sltu $5, $4, $7 +; MMR6-NEXT: selnez $3, $4, $5 ; MMR6-NEXT: seleqz $5, $7, $5 ; MMR6-NEXT: or $3, $3, $5 ; MMR6-NEXT: and $3, $3, $8 @@ -4767,9 +4825,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMR6-NEXT: sc $4, 0($6) ; MMR6-NEXT: beqc $4, $zero, $BB11_1 ; MMR6-NEXT: # %bb.2: # %entry -; MMR6-NEXT: and $1, $2, $8 -; MMR6-NEXT: srlv $1, $1, $10 -; MMR6-NEXT: seh $1, $1 +; MMR6-NEXT: .insn ; MMR6-NEXT: # %bb.3: # %entry ; MMR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMR6-NEXT: # %bb.4: # %entry @@ -4795,10 +4851,13 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: $BB11_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) -; MIPS32-NEXT: and $2, $2, $8 -; MIPS32-NEXT: and $7, $7, $8 -; MIPS32-NEXT: sltu $5, $2, $7 -; MIPS32-NEXT: move $3, $2 +; MIPS32-NEXT: srav $4, $2, $10 +; MIPS32-NEXT: sll $4, $4, 24 +; MIPS32-NEXT: srl $4, $4, 24 +; MIPS32-NEXT: or $1, $zero, $4 +; MIPS32-NEXT: sllv $4, $4, $10 +; MIPS32-NEXT: sltu $5, $4, $7 +; MIPS32-NEXT: move $3, $4 ; MIPS32-NEXT: movz $3, $7, $5 ; MIPS32-NEXT: and $3, $3, $8 ; MIPS32-NEXT: and $4, $2, $9 @@ -4807,10 +4866,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: beqz $4, $BB11_1 ; MIPS32-NEXT: nop ; MIPS32-NEXT: # %bb.2: # %entry -; MIPS32-NEXT: and $1, $2, $8 -; MIPS32-NEXT: srlv $1, $1, $10 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $1, $1, 16 +; MIPS32-NEXT: .insn ; MIPS32-NEXT: # %bb.3: # %entry ; MIPS32-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPS32-NEXT: # %bb.4: # %entry @@ -4837,10 +4893,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: $BB11_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) -; MIPSEL-NEXT: and $2, $2, $8 -; MIPSEL-NEXT: and $7, $7, $8 -; MIPSEL-NEXT: sltu $5, $2, $7 -; MIPSEL-NEXT: move $3, $2 +; MIPSEL-NEXT: srav $4, $2, $10 +; MIPSEL-NEXT: andi $4, $4, 255 +; MIPSEL-NEXT: or $1, $zero, $4 +; MIPSEL-NEXT: sllv $4, $4, $10 +; MIPSEL-NEXT: sltu $5, $4, $7 +; MIPSEL-NEXT: move $3, $4 ; MIPSEL-NEXT: movz $3, $7, $5 ; MIPSEL-NEXT: and $3, $3, $8 ; MIPSEL-NEXT: and $4, $2, $9 @@ -4849,9 +4907,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: beqz $4, $BB11_1 ; MIPSEL-NEXT: nop ; MIPSEL-NEXT: # %bb.2: # %entry -; MIPSEL-NEXT: and $1, $2, $8 -; MIPSEL-NEXT: srlv $1, $1, $10 -; MIPSEL-NEXT: seh $1, $1 +; MIPSEL-NEXT: .insn ; MIPSEL-NEXT: # %bb.3: # %entry ; MIPSEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSEL-NEXT: # %bb.4: # %entry @@ -4878,10 +4934,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: $BB11_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) -; MIPSELR6-NEXT: and $2, $2, $8 -; MIPSELR6-NEXT: and $7, $7, $8 -; MIPSELR6-NEXT: sltu $5, $2, $7 -; MIPSELR6-NEXT: selnez $3, $2, $5 +; MIPSELR6-NEXT: srav $4, $2, $10 +; MIPSELR6-NEXT: andi $4, $4, 255 +; MIPSELR6-NEXT: or $1, $zero, $4 +; MIPSELR6-NEXT: sllv $4, $4, $10 +; MIPSELR6-NEXT: sltu $5, $4, $7 +; MIPSELR6-NEXT: selnez $3, $4, $5 ; MIPSELR6-NEXT: seleqz $5, $7, $5 ; MIPSELR6-NEXT: or $3, $3, $5 ; MIPSELR6-NEXT: and $3, $3, $8 @@ -4889,10 +4947,9 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: or $4, $4, $3 ; MIPSELR6-NEXT: sc $4, 0($6) ; MIPSELR6-NEXT: beqzc $4, $BB11_1 +; MIPSELR6-NEXT: nop ; MIPSELR6-NEXT: # %bb.2: # %entry -; MIPSELR6-NEXT: and $1, $2, $8 -; MIPSELR6-NEXT: srlv $1, $1, $10 -; MIPSELR6-NEXT: seh $1, $1 +; MIPSELR6-NEXT: .insn ; MIPSELR6-NEXT: # %bb.3: # %entry ; MIPSELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MIPSELR6-NEXT: # %bb.4: # %entry @@ -4918,10 +4975,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: $BB11_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) -; MMEL-NEXT: and $2, $2, $8 -; MMEL-NEXT: and $7, $7, $8 -; MMEL-NEXT: sltu $5, $2, $7 -; MMEL-NEXT: or $3, $2, $zero +; MMEL-NEXT: srav $4, $2, $10 +; MMEL-NEXT: andi $4, $4, 255 +; MMEL-NEXT: or $1, $zero, $4 +; MMEL-NEXT: sllv $4, $4, $10 +; MMEL-NEXT: sltu $5, $4, $7 +; MMEL-NEXT: or $3, $4, $zero ; MMEL-NEXT: movz $3, $7, $5 ; MMEL-NEXT: and $3, $3, $8 ; MMEL-NEXT: and $4, $2, $9 @@ -4929,9 +4988,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: sc $4, 0($6) ; MMEL-NEXT: beqzc $4, $BB11_1 ; MMEL-NEXT: # %bb.2: # %entry -; MMEL-NEXT: and $1, $2, $8 -; MMEL-NEXT: srlv $1, $1, $10 -; MMEL-NEXT: seh $1, $1 +; MMEL-NEXT: .insn ; MMEL-NEXT: # %bb.3: # %entry ; MMEL-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMEL-NEXT: # %bb.4: # %entry @@ -4957,10 +5014,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: $BB11_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) -; MMELR6-NEXT: and $2, $2, $8 -; MMELR6-NEXT: and $7, $7, $8 -; MMELR6-NEXT: sltu $5, $2, $7 -; MMELR6-NEXT: selnez $3, $2, $5 +; MMELR6-NEXT: srav $4, $2, $10 +; MMELR6-NEXT: andi $4, $4, 255 +; MMELR6-NEXT: or $1, $zero, $4 +; MMELR6-NEXT: sllv $4, $4, $10 +; MMELR6-NEXT: sltu $5, $4, $7 +; MMELR6-NEXT: selnez $3, $4, $5 ; MMELR6-NEXT: seleqz $5, $7, $5 ; MMELR6-NEXT: or $3, $3, $5 ; MMELR6-NEXT: and $3, $3, $8 @@ -4969,9 +5028,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: sc $4, 0($6) ; MMELR6-NEXT: beqc $4, $zero, $BB11_1 ; MMELR6-NEXT: # %bb.2: # %entry -; MMELR6-NEXT: and $1, $2, $8 -; MMELR6-NEXT: srlv $1, $1, $10 -; MMELR6-NEXT: seh $1, $1 +; MMELR6-NEXT: .insn ; MMELR6-NEXT: # %bb.3: # %entry ; MMELR6-NEXT: sw $1, 4($sp) # 4-byte Folded Spill ; MMELR6-NEXT: # %bb.4: # %entry @@ -4998,8 +5055,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: .LBB11_1: # %entry ; MIPS64-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64-NEXT: ll $2, 0($6) -; MIPS64-NEXT: sltu $5, $2, $7 -; MIPS64-NEXT: move $3, $2 +; MIPS64-NEXT: srav $4, $2, $10 +; MIPS64-NEXT: andi $4, $4, 255 +; MIPS64-NEXT: or $1, $zero, $4 +; MIPS64-NEXT: sllv $4, $4, $10 +; MIPS64-NEXT: sltu $5, $4, $7 +; MIPS64-NEXT: move $3, $4 ; MIPS64-NEXT: movz $3, $7, $5 ; MIPS64-NEXT: and $3, $3, $8 ; MIPS64-NEXT: and $4, $2, $9 @@ -5008,9 +5069,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64-NEXT: beqz $4, .LBB11_1 ; MIPS64-NEXT: nop ; MIPS64-NEXT: # %bb.2: # %entry -; MIPS64-NEXT: and $1, $2, $8 -; MIPS64-NEXT: srlv $1, $1, $10 -; MIPS64-NEXT: seh $1, $1 +; MIPS64-NEXT: .insn ; MIPS64-NEXT: # %bb.3: # %entry ; MIPS64-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64-NEXT: # %bb.4: # %entry @@ -5038,8 +5097,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: .LBB11_1: # %entry ; MIPS64R6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64R6-NEXT: ll $2, 0($6) -; MIPS64R6-NEXT: sltu $5, $2, $7 -; MIPS64R6-NEXT: selnez $3, $2, $5 +; MIPS64R6-NEXT: srav $4, $2, $10 +; MIPS64R6-NEXT: andi $4, $4, 255 +; MIPS64R6-NEXT: or $1, $zero, $4 +; MIPS64R6-NEXT: sllv $4, $4, $10 +; MIPS64R6-NEXT: sltu $5, $4, $7 +; MIPS64R6-NEXT: selnez $3, $4, $5 ; MIPS64R6-NEXT: seleqz $5, $7, $5 ; MIPS64R6-NEXT: or $3, $3, $5 ; MIPS64R6-NEXT: and $3, $3, $8 @@ -5047,10 +5110,9 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64R6-NEXT: or $4, $4, $3 ; MIPS64R6-NEXT: sc $4, 0($6) ; MIPS64R6-NEXT: beqzc $4, .LBB11_1 +; MIPS64R6-NEXT: nop ; MIPS64R6-NEXT: # %bb.2: # %entry -; MIPS64R6-NEXT: and $1, $2, $8 -; MIPS64R6-NEXT: srlv $1, $1, $10 -; MIPS64R6-NEXT: seh $1, $1 +; MIPS64R6-NEXT: .insn ; MIPS64R6-NEXT: # %bb.3: # %entry ; MIPS64R6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64R6-NEXT: # %bb.4: # %entry @@ -5076,10 +5138,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: .LBB11_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) -; MIPS64EL-NEXT: and $2, $2, $8 -; MIPS64EL-NEXT: and $7, $7, $8 -; MIPS64EL-NEXT: sltu $5, $2, $7 -; MIPS64EL-NEXT: move $3, $2 +; MIPS64EL-NEXT: srav $4, $2, $10 +; MIPS64EL-NEXT: andi $4, $4, 255 +; MIPS64EL-NEXT: or $1, $zero, $4 +; MIPS64EL-NEXT: sllv $4, $4, $10 +; MIPS64EL-NEXT: sltu $5, $4, $7 +; MIPS64EL-NEXT: move $3, $4 ; MIPS64EL-NEXT: movz $3, $7, $5 ; MIPS64EL-NEXT: and $3, $3, $8 ; MIPS64EL-NEXT: and $4, $2, $9 @@ -5088,9 +5152,7 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: beqz $4, .LBB11_1 ; MIPS64EL-NEXT: nop ; MIPS64EL-NEXT: # %bb.2: # %entry -; MIPS64EL-NEXT: and $1, $2, $8 -; MIPS64EL-NEXT: srlv $1, $1, $10 -; MIPS64EL-NEXT: seh $1, $1 +; MIPS64EL-NEXT: .insn ; MIPS64EL-NEXT: # %bb.3: # %entry ; MIPS64EL-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64EL-NEXT: # %bb.4: # %entry @@ -5117,10 +5179,12 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: .LBB11_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) -; MIPS64ELR6-NEXT: and $2, $2, $8 -; MIPS64ELR6-NEXT: and $7, $7, $8 -; MIPS64ELR6-NEXT: sltu $5, $2, $7 -; MIPS64ELR6-NEXT: selnez $3, $2, $5 +; MIPS64ELR6-NEXT: srav $4, $2, $10 +; MIPS64ELR6-NEXT: andi $4, $4, 255 +; MIPS64ELR6-NEXT: or $1, $zero, $4 +; MIPS64ELR6-NEXT: sllv $4, $4, $10 +; MIPS64ELR6-NEXT: sltu $5, $4, $7 +; MIPS64ELR6-NEXT: selnez $3, $4, $5 ; MIPS64ELR6-NEXT: seleqz $5, $7, $5 ; MIPS64ELR6-NEXT: or $3, $3, $5 ; MIPS64ELR6-NEXT: and $3, $3, $8 @@ -5128,10 +5192,9 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: or $4, $4, $3 ; MIPS64ELR6-NEXT: sc $4, 0($6) ; MIPS64ELR6-NEXT: beqzc $4, .LBB11_1 +; MIPS64ELR6-NEXT: nop ; MIPS64ELR6-NEXT: # %bb.2: # %entry -; MIPS64ELR6-NEXT: and $1, $2, $8 -; MIPS64ELR6-NEXT: srlv $1, $1, $10 -; MIPS64ELR6-NEXT: seh $1, $1 +; MIPS64ELR6-NEXT: .insn ; MIPS64ELR6-NEXT: # %bb.3: # %entry ; MIPS64ELR6-NEXT: sw $1, 12($sp) # 4-byte Folded Spill ; MIPS64ELR6-NEXT: # %bb.4: # %entry -- GitLab From 2834e8ad1cfe32b69a8b5a1dd2477725683a61c4 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Mon, 22 Apr 2024 13:32:40 -0500 Subject: [PATCH 205/357] [lldb][NFC] Remove unused pexpect/ptyprocess (#89609) --- .../Python/module/pexpect-4.6/.gitignore | 11 - .../Python/module/pexpect-4.6/.travis.yml | 31 - .../Python/module/pexpect-4.6/DEVELOPERS.rst | 12 - .../Python/module/pexpect-4.6/LICENSE | 20 - .../Python/module/pexpect-4.6/MANIFEST.in | 6 - .../Python/module/pexpect-4.6/README.rst | 55 -- .../Python/module/pexpect-4.6/pexpect/ANSI.py | 351 -------- .../Python/module/pexpect-4.6/pexpect/FSM.py | 334 ------- .../module/pexpect-4.6/pexpect/__init__.py | 85 -- .../module/pexpect-4.6/pexpect/_async.py | 87 -- .../module/pexpect-4.6/pexpect/bashrc.sh | 16 - .../module/pexpect-4.6/pexpect/exceptions.py | 35 - .../module/pexpect-4.6/pexpect/expect.py | 306 ------- .../module/pexpect-4.6/pexpect/fdpexpect.py | 148 ---- .../module/pexpect-4.6/pexpect/popen_spawn.py | 188 ---- .../module/pexpect-4.6/pexpect/pty_spawn.py | 833 ----------------- .../module/pexpect-4.6/pexpect/pxssh.py | 499 ----------- .../module/pexpect-4.6/pexpect/replwrap.py | 122 --- .../Python/module/pexpect-4.6/pexpect/run.py | 157 ---- .../module/pexpect-4.6/pexpect/screen.py | 431 --------- .../module/pexpect-4.6/pexpect/spawnbase.py | 522 ----------- .../module/pexpect-4.6/pexpect/utils.py | 187 ---- .../pexpect-4.6/requirements-testing.txt | 5 - .../Python/module/pexpect-4.6/setup.cfg | 5 - .../Python/module/pexpect-4.6/setup.py | 71 -- .../Python/module/ptyprocess-0.6.0/.gitignore | 7 - .../module/ptyprocess-0.6.0/.travis.yml | 9 - .../Python/module/ptyprocess-0.6.0/LICENSE | 16 - .../Python/module/ptyprocess-0.6.0/README.rst | 15 - .../ptyprocess-0.6.0/ptyprocess/__init__.py | 4 - .../ptyprocess-0.6.0/ptyprocess/_fork_pty.py | 78 -- .../ptyprocess-0.6.0/ptyprocess/ptyprocess.py | 836 ------------------ .../ptyprocess-0.6.0/ptyprocess/util.py | 71 -- .../module/ptyprocess-0.6.0/pyproject.toml | 24 - .../module/ptyprocess-0.6.0/readthedocs.yml | 2 - 35 files changed, 5579 deletions(-) delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/.gitignore delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/.travis.yml delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/LICENSE delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/README.rst delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/setup.cfg delete mode 100644 lldb/third_party/Python/module/pexpect-4.6/setup.py delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/.gitignore delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/.travis.yml delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/README.rst delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/pyproject.toml delete mode 100644 lldb/third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml diff --git a/lldb/third_party/Python/module/pexpect-4.6/.gitignore b/lldb/third_party/Python/module/pexpect-4.6/.gitignore deleted file mode 100644 index 22cd4785f715..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.pyc -doc/_build -tests/log -build/ -dist/ -MANIFEST -*~ -.coverage* -htmlcov -*.egg-info/ -.cache/ diff --git a/lldb/third_party/Python/module/pexpect-4.6/.travis.yml b/lldb/third_party/Python/module/pexpect-4.6/.travis.yml deleted file mode 100644 index 40d962295012..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: python - -python: - - 2.7 - - 3.3 - - 3.4 - - 3.5 - - 3.6 - - pypy - - nightly - -matrix: - allow_failures: - # PyPy on Travis is currently incompatible with Cryptography. - - python: pypy - -install: - - export PYTHONIOENCODING=UTF8 - - pip install coveralls pytest-cov ptyprocess - -script: - - ./tools/display-sighandlers.py - - ./tools/display-terminalinfo.py - - py.test --cov pexpect --cov-config .coveragerc - -after_success: - - coverage combine - - coveralls - -# Use new Travis stack, should be faster -sudo: false diff --git a/lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst b/lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst deleted file mode 100644 index bf2bb9f30f8a..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/DEVELOPERS.rst +++ /dev/null @@ -1,12 +0,0 @@ -To run the tests, use `py.test `_:: - - py.test tests - -The tests are all located in the tests/ directory. To add a new unit -test all you have to do is create the file in the tests/ directory with a -filename in this format:: - - test_*.py - -New test case classes may wish to inherit from ``PexpectTestCase.PexpectTestCase`` -in the tests directory, which sets up some convenient functionality. diff --git a/lldb/third_party/Python/module/pexpect-4.6/LICENSE b/lldb/third_party/Python/module/pexpect-4.6/LICENSE deleted file mode 100644 index 754db5afcb82..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -ISC LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2013-2014, Pexpect development team - Copyright (c) 2012, Noah Spurrier - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - diff --git a/lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in b/lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in deleted file mode 100644 index 32c72ba17124..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -recursive-include doc * -prune doc/_build -recursive-include examples * -include .coveragerc README.rst LICENSE pexpect/bashrc.sh -recursive-include tests * -global-exclude __pycache__ *.pyc *~ diff --git a/lldb/third_party/Python/module/pexpect-4.6/README.rst b/lldb/third_party/Python/module/pexpect-4.6/README.rst deleted file mode 100644 index 0f5cb98ceb98..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/README.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. image:: https://travis-ci.org/pexpect/pexpect.svg?branch=master - :target: https://travis-ci.org/pexpect/pexpect - :align: right - :alt: Build status - -Pexpect is a Pure Python Expect-like module - -Pexpect makes Python a better tool for controlling other applications. - -Pexpect is a pure Python module for spawning child applications; controlling -them; and responding to expected patterns in their output. Pexpect works like -Don Libes' Expect. Pexpect allows your script to spawn a child application and -control it as if a human were typing commands. - -Pexpect can be used for automating interactive applications such as ssh, ftp, -passwd, telnet, etc. It can be used to a automate setup scripts for duplicating -software package installations on different servers. It can be used for -automated software testing. Pexpect is in the spirit of Don Libes' Expect, but -Pexpect is pure Python. - -The main features of Pexpect require the pty module in the Python standard -library, which is only available on Unix-like systems. Some features—waiting -for patterns from file descriptors or subprocesses—are also available on -Windows. - -If you want to work with the development version of the source code then please -read the DEVELOPERS.rst document in the root of the source code tree. - -Free, open source, and all that good stuff. - -You can install Pexpect using pip:: - - pip install pexpect - -`Docs on ReadTheDocs `_ - -PEXPECT LICENSE:: - - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2013-2016, Pexpect development team - Copyright (c) 2012, Noah Spurrier - - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -This license is approved by the OSI and FSF as GPL-compatible. diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py deleted file mode 100644 index 1cd2e90e7ab0..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/ANSI.py +++ /dev/null @@ -1,351 +0,0 @@ -'''This implements an ANSI (VT100) terminal emulator as a subclass of screen. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -# references: -# http://en.wikipedia.org/wiki/ANSI_escape_code -# http://www.retards.org/terminals/vt102.html -# http://vt100.net/docs/vt102-ug/contents.html -# http://vt100.net/docs/vt220-rm/ -# http://www.termsys.demon.co.uk/vtansi.htm - -from . import screen -from . import FSM -import string - -# -# The 'Do.*' functions are helper functions for the ANSI class. -# -def DoEmit (fsm): - - screen = fsm.memory[0] - screen.write_ch(fsm.input_symbol) - -def DoStartNumber (fsm): - - fsm.memory.append (fsm.input_symbol) - -def DoBuildNumber (fsm): - - ns = fsm.memory.pop() - ns = ns + fsm.input_symbol - fsm.memory.append (ns) - -def DoBackOne (fsm): - - screen = fsm.memory[0] - screen.cursor_back () - -def DoBack (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_back (count) - -def DoDownOne (fsm): - - screen = fsm.memory[0] - screen.cursor_down () - -def DoDown (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_down (count) - -def DoForwardOne (fsm): - - screen = fsm.memory[0] - screen.cursor_forward () - -def DoForward (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_forward (count) - -def DoUpReverse (fsm): - - screen = fsm.memory[0] - screen.cursor_up_reverse() - -def DoUpOne (fsm): - - screen = fsm.memory[0] - screen.cursor_up () - -def DoUp (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_up (count) - -def DoHome (fsm): - - c = int(fsm.memory.pop()) - r = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_home (r,c) - -def DoHomeOrigin (fsm): - - c = 1 - r = 1 - screen = fsm.memory[0] - screen.cursor_home (r,c) - -def DoEraseDown (fsm): - - screen = fsm.memory[0] - screen.erase_down() - -def DoErase (fsm): - - arg = int(fsm.memory.pop()) - screen = fsm.memory[0] - if arg == 0: - screen.erase_down() - elif arg == 1: - screen.erase_up() - elif arg == 2: - screen.erase_screen() - -def DoEraseEndOfLine (fsm): - - screen = fsm.memory[0] - screen.erase_end_of_line() - -def DoEraseLine (fsm): - - arg = int(fsm.memory.pop()) - screen = fsm.memory[0] - if arg == 0: - screen.erase_end_of_line() - elif arg == 1: - screen.erase_start_of_line() - elif arg == 2: - screen.erase_line() - -def DoEnableScroll (fsm): - - screen = fsm.memory[0] - screen.scroll_screen() - -def DoCursorSave (fsm): - - screen = fsm.memory[0] - screen.cursor_save_attrs() - -def DoCursorRestore (fsm): - - screen = fsm.memory[0] - screen.cursor_restore_attrs() - -def DoScrollRegion (fsm): - - screen = fsm.memory[0] - r2 = int(fsm.memory.pop()) - r1 = int(fsm.memory.pop()) - screen.scroll_screen_rows (r1,r2) - -def DoMode (fsm): - - screen = fsm.memory[0] - mode = fsm.memory.pop() # Should be 4 - # screen.setReplaceMode () - -def DoLog (fsm): - - screen = fsm.memory[0] - fsm.memory = [screen] - fout = open ('log', 'a') - fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n') - fout.close() - -class term (screen.screen): - - '''This class is an abstract, generic terminal. - This does nothing. This is a placeholder that - provides a common base class for other terminals - such as an ANSI terminal. ''' - - def __init__ (self, r=24, c=80, *args, **kwargs): - - screen.screen.__init__(self, r,c,*args,**kwargs) - -class ANSI (term): - '''This class implements an ANSI (VT100) terminal. - It is a stream filter that recognizes ANSI terminal - escape sequences and maintains the state of a screen object. ''' - - def __init__ (self, r=24,c=80,*args,**kwargs): - - term.__init__(self,r,c,*args,**kwargs) - - #self.screen = screen (24,80) - self.state = FSM.FSM ('INIT',[self]) - self.state.set_default_transition (DoLog, 'INIT') - self.state.add_transition_any ('INIT', DoEmit, 'INIT') - self.state.add_transition ('\x1b', 'INIT', None, 'ESC') - self.state.add_transition_any ('ESC', DoLog, 'INIT') - self.state.add_transition ('(', 'ESC', None, 'G0SCS') - self.state.add_transition (')', 'ESC', None, 'G1SCS') - self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT') - self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT') - self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT') - self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT') - self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT') - self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT') - self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT') - self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad. - self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND') - self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT') - self.state.add_transition ('[', 'ESC', None, 'ELB') - # ELB means Escape Left Bracket. That is ^[[ - self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT') - self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT') - self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT') - self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT') - self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT') - self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT') - self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT') - self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT') - self.state.add_transition ('m', 'ELB', self.do_sgr, 'INIT') - self.state.add_transition ('?', 'ELB', None, 'MODECRAP') - self.state.add_transition_list (string.digits, 'ELB', DoStartNumber, 'NUMBER_1') - self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, 'NUMBER_1') - self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT') - self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT') - self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT') - self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT') - self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT') - self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT') - self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT') - ### It gets worse... the 'm' code can have infinite number of - ### number;number;number before it. I've never seen more than two, - ### but the specs say it's allowed. crap! - self.state.add_transition ('m', 'NUMBER_1', self.do_sgr, 'INIT') - ### LED control. Same implementation problem as 'm' code. - self.state.add_transition ('q', 'NUMBER_1', self.do_decsca, 'INIT') - - # \E[?47h switch to alternate screen - # \E[?47l restores to normal screen from alternate screen. - self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM') - self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, 'MODECRAP_NUM') - self.state.add_transition ('l', 'MODECRAP_NUM', self.do_modecrap, 'INIT') - self.state.add_transition ('h', 'MODECRAP_NUM', self.do_modecrap, 'INIT') - -#RM Reset Mode Esc [ Ps l none - self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON') - self.state.add_transition_any ('SEMICOLON', DoLog, 'INIT') - self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2') - self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2') - self.state.add_transition_any ('NUMBER_2', DoLog, 'INIT') - self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT') - self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT') - self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT') - ### It gets worse... the 'm' code can have infinite number of - ### number;number;number before it. I've never seen more than two, - ### but the specs say it's allowed. crap! - self.state.add_transition ('m', 'NUMBER_2', self.do_sgr, 'INIT') - ### LED control. Same problem as 'm' code. - self.state.add_transition ('q', 'NUMBER_2', self.do_decsca, 'INIT') - self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X') - - # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers - self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT') - self.state.add_transition_list (string.digits, 'SEMICOLON_X', DoStartNumber, 'NUMBER_X') - self.state.add_transition_list (string.digits, 'NUMBER_X', DoBuildNumber, 'NUMBER_X') - self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT') - self.state.add_transition ('m', 'NUMBER_X', self.do_sgr, 'INIT') - self.state.add_transition ('q', 'NUMBER_X', self.do_decsca, 'INIT') - self.state.add_transition (';', 'NUMBER_X', None, 'SEMICOLON_X') - - def process (self, c): - """Process a single character. Called by :meth:`write`.""" - if isinstance(c, bytes): - c = self._decode(c) - self.state.process(c) - - def process_list (self, l): - - self.write(l) - - def write (self, s): - """Process text, writing it to the virtual screen while handling - ANSI escape codes. - """ - if isinstance(s, bytes): - s = self._decode(s) - for c in s: - self.process(c) - - def flush (self): - pass - - def write_ch (self, ch): - '''This puts a character at the current cursor position. The cursor - position is moved forward with wrap-around, but no scrolling is done if - the cursor hits the lower-right corner of the screen. ''' - - if isinstance(ch, bytes): - ch = self._decode(ch) - - #\r and \n both produce a call to cr() and lf(), respectively. - ch = ch[0] - - if ch == u'\r': - self.cr() - return - if ch == u'\n': - self.crlf() - return - if ch == chr(screen.BS): - self.cursor_back() - return - self.put_abs(self.cur_r, self.cur_c, ch) - old_r = self.cur_r - old_c = self.cur_c - self.cursor_forward() - if old_c == self.cur_c: - self.cursor_down() - if old_r != self.cur_r: - self.cursor_home (self.cur_r, 1) - else: - self.scroll_up () - self.cursor_home (self.cur_r, 1) - self.erase_line() - - def do_sgr (self, fsm): - '''Select Graphic Rendition, e.g. color. ''' - screen = fsm.memory[0] - fsm.memory = [screen] - - def do_decsca (self, fsm): - '''Select character protection attribute. ''' - screen = fsm.memory[0] - fsm.memory = [screen] - - def do_modecrap (self, fsm): - '''Handler for \x1b[?h and \x1b[?l. If anyone - wanted to actually use these, they'd need to add more states to the - FSM rather than just improve or override this method. ''' - screen = fsm.memory[0] - fsm.memory = [screen] diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py deleted file mode 100644 index 46b392ea08aa..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/FSM.py +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/bin/env python - -'''This module implements a Finite State Machine (FSM). In addition to state -this FSM also maintains a user defined "memory". So this FSM can be used as a -Push-down Automata (PDA) since a PDA is a FSM + memory. - -The following describes how the FSM works, but you will probably also need to -see the example function to understand how the FSM is used in practice. - -You define an FSM by building tables of transitions. For a given input symbol -the process() method uses these tables to decide what action to call and what -the next state will be. The FSM has a table of transitions that associate: - - (input_symbol, current_state) --> (action, next_state) - -Where "action" is a function you define. The symbols and states can be any -objects. You use the add_transition() and add_transition_list() methods to add -to the transition table. The FSM also has a table of transitions that -associate: - - (current_state) --> (action, next_state) - -You use the add_transition_any() method to add to this transition table. The -FSM also has one default transition that is not associated with any specific -input_symbol or state. You use the set_default_transition() method to set the -default transition. - -When an action function is called it is passed a reference to the FSM. The -action function may then access attributes of the FSM such as input_symbol, -current_state, or "memory". The "memory" attribute can be any object that you -want to pass along to the action functions. It is not used by the FSM itself. -For parsing you would typically pass a list to be used as a stack. - -The processing sequence is as follows. The process() method is given an -input_symbol to process. The FSM will search the table of transitions that -associate: - - (input_symbol, current_state) --> (action, next_state) - -If the pair (input_symbol, current_state) is found then process() will call the -associated action function and then set the current state to the next_state. - -If the FSM cannot find a match for (input_symbol, current_state) it will then -search the table of transitions that associate: - - (current_state) --> (action, next_state) - -If the current_state is found then the process() method will call the -associated action function and then set the current state to the next_state. -Notice that this table lacks an input_symbol. It lets you define transitions -for a current_state and ANY input_symbol. Hence, it is called the "any" table. -Remember, it is always checked after first searching the table for a specific -(input_symbol, current_state). - -For the case where the FSM did not match either of the previous two cases the -FSM will try to use the default transition. If the default transition is -defined then the process() method will call the associated action function and -then set the current state to the next_state. This lets you define a default -transition as a catch-all case. You can think of it as an exception handler. -There can be only one default transition. - -Finally, if none of the previous cases are defined for an input_symbol and -current_state then the FSM will raise an exception. This may be desirable, but -you can always prevent this just by defining a default transition. - -Noah Spurrier 20020822 - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -class ExceptionFSM(Exception): - - '''This is the FSM Exception class.''' - - def __init__(self, value): - self.value = value - - def __str__(self): - return 'ExceptionFSM: ' + str(self.value) - -class FSM: - - '''This is a Finite State Machine (FSM). - ''' - - def __init__(self, initial_state, memory=None): - - '''This creates the FSM. You set the initial state here. The "memory" - attribute is any object that you want to pass along to the action - functions. It is not used by the FSM. For parsing you would typically - pass a list to be used as a stack. ''' - - # Map (input_symbol, current_state) --> (action, next_state). - self.state_transitions = {} - # Map (current_state) --> (action, next_state). - self.state_transitions_any = {} - self.default_transition = None - - self.input_symbol = None - self.initial_state = initial_state - self.current_state = self.initial_state - self.next_state = None - self.action = None - self.memory = memory - - def reset (self): - - '''This sets the current_state to the initial_state and sets - input_symbol to None. The initial state was set by the constructor - __init__(). ''' - - self.current_state = self.initial_state - self.input_symbol = None - - def add_transition (self, input_symbol, state, action=None, next_state=None): - - '''This adds a transition that associates: - - (input_symbol, current_state) --> (action, next_state) - - The action may be set to None in which case the process() method will - ignore the action and only set the next_state. The next_state may be - set to None in which case the current state will be unchanged. - - You can also set transitions for a list of symbols by using - add_transition_list(). ''' - - if next_state is None: - next_state = state - self.state_transitions[(input_symbol, state)] = (action, next_state) - - def add_transition_list (self, list_input_symbols, state, action=None, next_state=None): - - '''This adds the same transition for a list of input symbols. - You can pass a list or a string. Note that it is handy to use - string.digits, string.whitespace, string.letters, etc. to add - transitions that match character classes. - - The action may be set to None in which case the process() method will - ignore the action and only set the next_state. The next_state may be - set to None in which case the current state will be unchanged. ''' - - if next_state is None: - next_state = state - for input_symbol in list_input_symbols: - self.add_transition (input_symbol, state, action, next_state) - - def add_transition_any (self, state, action=None, next_state=None): - - '''This adds a transition that associates: - - (current_state) --> (action, next_state) - - That is, any input symbol will match the current state. - The process() method checks the "any" state associations after it first - checks for an exact match of (input_symbol, current_state). - - The action may be set to None in which case the process() method will - ignore the action and only set the next_state. The next_state may be - set to None in which case the current state will be unchanged. ''' - - if next_state is None: - next_state = state - self.state_transitions_any [state] = (action, next_state) - - def set_default_transition (self, action, next_state): - - '''This sets the default transition. This defines an action and - next_state if the FSM cannot find the input symbol and the current - state in the transition list and if the FSM cannot find the - current_state in the transition_any list. This is useful as a final - fall-through state for catching errors and undefined states. - - The default transition can be removed by setting the attribute - default_transition to None. ''' - - self.default_transition = (action, next_state) - - def get_transition (self, input_symbol, state): - - '''This returns (action, next state) given an input_symbol and state. - This does not modify the FSM state, so calling this method has no side - effects. Normally you do not call this method directly. It is called by - process(). - - The sequence of steps to check for a defined transition goes from the - most specific to the least specific. - - 1. Check state_transitions[] that match exactly the tuple, - (input_symbol, state) - - 2. Check state_transitions_any[] that match (state) - In other words, match a specific state and ANY input_symbol. - - 3. Check if the default_transition is defined. - This catches any input_symbol and any state. - This is a handler for errors, undefined states, or defaults. - - 4. No transition was defined. If we get here then raise an exception. - ''' - - if (input_symbol, state) in self.state_transitions: - return self.state_transitions[(input_symbol, state)] - elif state in self.state_transitions_any: - return self.state_transitions_any[state] - elif self.default_transition is not None: - return self.default_transition - else: - raise ExceptionFSM ('Transition is undefined: (%s, %s).' % - (str(input_symbol), str(state)) ) - - def process (self, input_symbol): - - '''This is the main method that you call to process input. This may - cause the FSM to change state and call an action. This method calls - get_transition() to find the action and next_state associated with the - input_symbol and current_state. If the action is None then the action - is not called and only the current state is changed. This method - processes one complete input symbol. You can process a list of symbols - (or a string) by calling process_list(). ''' - - self.input_symbol = input_symbol - (self.action, self.next_state) = self.get_transition (self.input_symbol, self.current_state) - if self.action is not None: - self.action (self) - self.current_state = self.next_state - self.next_state = None - - def process_list (self, input_symbols): - - '''This takes a list and sends each element to process(). The list may - be a string or any iterable object. ''' - - for s in input_symbols: - self.process (s) - -############################################################################## -# The following is an example that demonstrates the use of the FSM class to -# process an RPN expression. Run this module from the command line. You will -# get a prompt > for input. Enter an RPN Expression. Numbers may be integers. -# Operators are * / + - Use the = sign to evaluate and print the expression. -# For example: -# -# 167 3 2 2 * * * 1 - = -# -# will print: -# -# 2003 -############################################################################## - -import sys -import string - -PY3 = (sys.version_info[0] >= 3) - -# -# These define the actions. -# Note that "memory" is a list being used as a stack. -# - -def BeginBuildNumber (fsm): - fsm.memory.append (fsm.input_symbol) - -def BuildNumber (fsm): - s = fsm.memory.pop () - s = s + fsm.input_symbol - fsm.memory.append (s) - -def EndBuildNumber (fsm): - s = fsm.memory.pop () - fsm.memory.append (int(s)) - -def DoOperator (fsm): - ar = fsm.memory.pop() - al = fsm.memory.pop() - if fsm.input_symbol == '+': - fsm.memory.append (al + ar) - elif fsm.input_symbol == '-': - fsm.memory.append (al - ar) - elif fsm.input_symbol == '*': - fsm.memory.append (al * ar) - elif fsm.input_symbol == '/': - fsm.memory.append (al / ar) - -def DoEqual (fsm): - print(str(fsm.memory.pop())) - -def Error (fsm): - print('That does not compute.') - print(str(fsm.input_symbol)) - -def main(): - - '''This is where the example starts and the FSM state transitions are - defined. Note that states are strings (such as 'INIT'). This is not - necessary, but it makes the example easier to read. ''' - - f = FSM ('INIT', []) - f.set_default_transition (Error, 'INIT') - f.add_transition_any ('INIT', None, 'INIT') - f.add_transition ('=', 'INIT', DoEqual, 'INIT') - f.add_transition_list (string.digits, 'INIT', BeginBuildNumber, 'BUILDING_NUMBER') - f.add_transition_list (string.digits, 'BUILDING_NUMBER', BuildNumber, 'BUILDING_NUMBER') - f.add_transition_list (string.whitespace, 'BUILDING_NUMBER', EndBuildNumber, 'INIT') - f.add_transition_list ('+-*/', 'INIT', DoOperator, 'INIT') - - print() - print('Enter an RPN Expression.') - print('Numbers may be integers. Operators are * / + -') - print('Use the = sign to evaluate and print the expression.') - print('For example: ') - print(' 167 3 2 2 * * * 1 - =') - inputstr = (input if PY3 else raw_input)('> ') # analysis:ignore - f.process_list(inputstr) - - -if __name__ == '__main__': - main() diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py deleted file mode 100644 index 2a18d1911a9c..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -'''Pexpect is a Python module for spawning child applications and controlling -them automatically. Pexpect can be used for automating interactive applications -such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup -scripts for duplicating software package installations on different servers. It -can be used for automated software testing. Pexpect is in the spirit of Don -Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python -require TCL and Expect or require C extensions to be compiled. Pexpect does not -use C, Expect, or TCL extensions. It should work on any platform that supports -the standard Python pty module. The Pexpect interface focuses on ease of use so -that simple tasks are easy. - -There are two main interfaces to the Pexpect system; these are the function, -run() and the class, spawn. The spawn class is more powerful. The run() -function is simpler than spawn, and is good for quickly calling program. When -you call the run() function it executes a given program and then returns the -output. This is a handy replacement for os.system(). - -For example:: - - pexpect.run('ls -la') - -The spawn class is the more powerful interface to the Pexpect system. You can -use this to spawn a child program then interact with it by sending input and -expecting responses (waiting for patterns in the child's output). - -For example:: - - child = pexpect.spawn('scp foo user@example.com:.') - child.expect('Password:') - child.sendline(mypassword) - -This works even for commands that ask for passwords or other input outside of -the normal stdio streams. For example, ssh reads input directly from the TTY -device which bypasses stdin. - -Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett, -Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids -vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin, -Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey, -Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume -Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John -Spiegel, Jan Grant, and Shane Kerr. Let me know if I forgot anyone. - -Pexpect is free, open source, and all that good stuff. -http://pexpect.sourceforge.net/ - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -import sys -PY3 = (sys.version_info[0] >= 3) - -from .exceptions import ExceptionPexpect, EOF, TIMEOUT -from .utils import split_command_line, which, is_executable_file -from .expect import Expecter, searcher_re, searcher_string - -if sys.platform != 'win32': - # On Unix, these are available at the top level for backwards compatibility - from .pty_spawn import spawn, spawnu - from .run import run, runu - -__version__ = '4.6.0' -__revision__ = '' -__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu', - 'which', 'split_command_line', '__version__', '__revision__'] - - - -# vim: set shiftround expandtab tabstop=4 shiftwidth=4 ft=python autoindent : diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py deleted file mode 100644 index bdd515b1f509..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/_async.py +++ /dev/null @@ -1,87 +0,0 @@ -import asyncio -import errno - -from pexpect import EOF - -@asyncio.coroutine -def expect_async(expecter, timeout=None): - # First process data that was previously read - if it maches, we don't need - # async stuff. - previously_read = expecter.spawn.buffer - expecter.spawn._buffer = expecter.spawn.buffer_type() - expecter.spawn._before = expecter.spawn.buffer_type() - idx = expecter.new_data(previously_read) - if idx is not None: - return idx - if not expecter.spawn.async_pw_transport: - pw = PatternWaiter() - pw.set_expecter(expecter) - transport, pw = yield from asyncio.get_event_loop()\ - .connect_read_pipe(lambda: pw, expecter.spawn) - expecter.spawn.async_pw_transport = pw, transport - else: - pw, transport = expecter.spawn.async_pw_transport - pw.set_expecter(expecter) - transport.resume_reading() - try: - return (yield from asyncio.wait_for(pw.fut, timeout)) - except asyncio.TimeoutError as e: - transport.pause_reading() - return expecter.timeout(e) - - -class PatternWaiter(asyncio.Protocol): - transport = None - - def set_expecter(self, expecter): - self.expecter = expecter - self.fut = asyncio.Future() - - def found(self, result): - if not self.fut.done(): - self.fut.set_result(result) - self.transport.pause_reading() - - def error(self, exc): - if not self.fut.done(): - self.fut.set_exception(exc) - self.transport.pause_reading() - - def connection_made(self, transport): - self.transport = transport - - def data_received(self, data): - spawn = self.expecter.spawn - s = spawn._decoder.decode(data) - spawn._log(s, 'read') - - if self.fut.done(): - spawn._buffer.write(s) - return - - try: - index = self.expecter.new_data(s) - if index is not None: - # Found a match - self.found(index) - except Exception as e: - self.expecter.errored() - self.error(e) - - def eof_received(self): - # N.B. If this gets called, async will close the pipe (the spawn object) - # for us - try: - self.expecter.spawn.flag_eof = True - index = self.expecter.eof() - except EOF as e: - self.error(e) - else: - self.found(index) - - def connection_lost(self, exc): - if isinstance(exc, OSError) and exc.errno == errno.EIO: - # We may get here without eof_received being called, e.g on Linux - self.eof_received() - elif exc is not None: - self.error(exc) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh b/lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh deleted file mode 100644 index c734ac90b852..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh +++ /dev/null @@ -1,16 +0,0 @@ -# Different platforms have different names for the systemwide bashrc -if [[ -f /etc/bashrc ]]; then - source /etc/bashrc -fi -if [[ -f /etc/bash.bashrc ]]; then - source /etc/bash.bashrc -fi -if [[ -f ~/.bashrc ]]; then - source ~/.bashrc -fi - -# Reset PS1 so pexpect can find it -PS1="$" - -# Unset PROMPT_COMMAND, so that it can't change PS1 to something unexpected. -unset PROMPT_COMMAND diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py deleted file mode 100644 index cb360f026143..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/exceptions.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Exception classes used by Pexpect""" - -import traceback -import sys - -class ExceptionPexpect(Exception): - '''Base class for all exceptions raised by this module. - ''' - - def __init__(self, value): - super(ExceptionPexpect, self).__init__(value) - self.value = value - - def __str__(self): - return str(self.value) - - def get_trace(self): - '''This returns an abbreviated stack trace with lines that only concern - the caller. In other words, the stack trace inside the Pexpect module - is not included. ''' - - tblist = traceback.extract_tb(sys.exc_info()[2]) - tblist = [item for item in tblist if ('pexpect/__init__' not in item[0]) - and ('pexpect/expect' not in item[0])] - tblist = traceback.format_list(tblist) - return ''.join(tblist) - - -class EOF(ExceptionPexpect): - '''Raised when EOF is read from a child. - This usually means the child has exited.''' - - -class TIMEOUT(ExceptionPexpect): - '''Raised when a read time exceeds the timeout. ''' diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py deleted file mode 100644 index 1c0275b4853a..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/expect.py +++ /dev/null @@ -1,306 +0,0 @@ -import time - -from .exceptions import EOF, TIMEOUT - -class Expecter(object): - def __init__(self, spawn, searcher, searchwindowsize=-1): - self.spawn = spawn - self.searcher = searcher - if searchwindowsize == -1: - searchwindowsize = spawn.searchwindowsize - self.searchwindowsize = searchwindowsize - - def new_data(self, data): - spawn = self.spawn - searcher = self.searcher - - pos = spawn._buffer.tell() - spawn._buffer.write(data) - spawn._before.write(data) - - # determine which chunk of data to search; if a windowsize is - # specified, this is the *new* data + the preceding bytes - if self.searchwindowsize: - spawn._buffer.seek(max(0, pos - self.searchwindowsize)) - window = spawn._buffer.read(self.searchwindowsize + len(data)) - else: - # otherwise, search the whole buffer (really slow for large datasets) - window = spawn.buffer - index = searcher.search(window, len(data)) - if index >= 0: - spawn._buffer = spawn.buffer_type() - spawn._buffer.write(window[searcher.end:]) - spawn.before = spawn._before.getvalue()[0:-(len(window) - searcher.start)] - spawn._before = spawn.buffer_type() - spawn.after = window[searcher.start: searcher.end] - spawn.match = searcher.match - spawn.match_index = index - # Found a match - return index - elif self.searchwindowsize: - spawn._buffer = spawn.buffer_type() - spawn._buffer.write(window) - - def eof(self, err=None): - spawn = self.spawn - - spawn.before = spawn.buffer - spawn._buffer = spawn.buffer_type() - spawn._before = spawn.buffer_type() - spawn.after = EOF - index = self.searcher.eof_index - if index >= 0: - spawn.match = EOF - spawn.match_index = index - return index - else: - spawn.match = None - spawn.match_index = None - msg = str(spawn) - msg += '\nsearcher: %s' % self.searcher - if err is not None: - msg = str(err) + '\n' + msg - raise EOF(msg) - - def timeout(self, err=None): - spawn = self.spawn - - spawn.before = spawn.buffer - spawn.after = TIMEOUT - index = self.searcher.timeout_index - if index >= 0: - spawn.match = TIMEOUT - spawn.match_index = index - return index - else: - spawn.match = None - spawn.match_index = None - msg = str(spawn) - msg += '\nsearcher: %s' % self.searcher - if err is not None: - msg = str(err) + '\n' + msg - raise TIMEOUT(msg) - - def errored(self): - spawn = self.spawn - spawn.before = spawn.buffer - spawn.after = None - spawn.match = None - spawn.match_index = None - - def expect_loop(self, timeout=-1): - """Blocking expect""" - spawn = self.spawn - - if timeout is not None: - end_time = time.time() + timeout - - try: - incoming = spawn.buffer - spawn._buffer = spawn.buffer_type() - spawn._before = spawn.buffer_type() - while True: - idx = self.new_data(incoming) - # Keep reading until exception or return. - if idx is not None: - return idx - # No match at this point - if (timeout is not None) and (timeout < 0): - return self.timeout() - # Still have time left, so read more data - incoming = spawn.read_nonblocking(spawn.maxread, timeout) - if self.spawn.delayafterread is not None: - time.sleep(self.spawn.delayafterread) - if timeout is not None: - timeout = end_time - time.time() - except EOF as e: - return self.eof(e) - except TIMEOUT as e: - return self.timeout(e) - except: - self.errored() - raise - - -class searcher_string(object): - '''This is a plain string search helper for the spawn.expect_any() method. - This helper class is for speed. For more powerful regex patterns - see the helper class, searcher_re. - - Attributes: - - eof_index - index of EOF, or -1 - timeout_index - index of TIMEOUT, or -1 - - After a successful match by the search() method the following attributes - are available: - - start - index into the buffer, first byte of match - end - index into the buffer, first byte after match - match - the matching string itself - - ''' - - def __init__(self, strings): - '''This creates an instance of searcher_string. This argument 'strings' - may be a list; a sequence of strings; or the EOF or TIMEOUT types. ''' - - self.eof_index = -1 - self.timeout_index = -1 - self._strings = [] - for n, s in enumerate(strings): - if s is EOF: - self.eof_index = n - continue - if s is TIMEOUT: - self.timeout_index = n - continue - self._strings.append((n, s)) - - def __str__(self): - '''This returns a human-readable string that represents the state of - the object.''' - - ss = [(ns[0], ' %d: %r' % ns) for ns in self._strings] - ss.append((-1, 'searcher_string:')) - if self.eof_index >= 0: - ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) - if self.timeout_index >= 0: - ss.append((self.timeout_index, - ' %d: TIMEOUT' % self.timeout_index)) - ss.sort() - ss = list(zip(*ss))[1] - return '\n'.join(ss) - - def search(self, buffer, freshlen, searchwindowsize=None): - '''This searches 'buffer' for the first occurrence of one of the search - strings. 'freshlen' must indicate the number of bytes at the end of - 'buffer' which have not been searched before. It helps to avoid - searching the same, possibly big, buffer over and over again. - - See class spawn for the 'searchwindowsize' argument. - - If there is a match this returns the index of that string, and sets - 'start', 'end' and 'match'. Otherwise, this returns -1. ''' - - first_match = None - - # 'freshlen' helps a lot here. Further optimizations could - # possibly include: - # - # using something like the Boyer-Moore Fast String Searching - # Algorithm; pre-compiling the search through a list of - # strings into something that can scan the input once to - # search for all N strings; realize that if we search for - # ['bar', 'baz'] and the input is '...foo' we need not bother - # rescanning until we've read three more bytes. - # - # Sadly, I don't know enough about this interesting topic. /grahn - - for index, s in self._strings: - if searchwindowsize is None: - # the match, if any, can only be in the fresh data, - # or at the very end of the old data - offset = -(freshlen + len(s)) - else: - # better obey searchwindowsize - offset = -searchwindowsize - n = buffer.find(s, offset) - if n >= 0 and (first_match is None or n < first_match): - first_match = n - best_index, best_match = index, s - if first_match is None: - return -1 - self.match = best_match - self.start = first_match - self.end = self.start + len(self.match) - return best_index - - -class searcher_re(object): - '''This is regular expression string search helper for the - spawn.expect_any() method. This helper class is for powerful - pattern matching. For speed, see the helper class, searcher_string. - - Attributes: - - eof_index - index of EOF, or -1 - timeout_index - index of TIMEOUT, or -1 - - After a successful match by the search() method the following attributes - are available: - - start - index into the buffer, first byte of match - end - index into the buffer, first byte after match - match - the re.match object returned by a successful re.search - - ''' - - def __init__(self, patterns): - '''This creates an instance that searches for 'patterns' Where - 'patterns' may be a list or other sequence of compiled regular - expressions, or the EOF or TIMEOUT types.''' - - self.eof_index = -1 - self.timeout_index = -1 - self._searches = [] - for n, s in zip(list(range(len(patterns))), patterns): - if s is EOF: - self.eof_index = n - continue - if s is TIMEOUT: - self.timeout_index = n - continue - self._searches.append((n, s)) - - def __str__(self): - '''This returns a human-readable string that represents the state of - the object.''' - - #ss = [(n, ' %d: re.compile("%s")' % - # (n, repr(s.pattern))) for n, s in self._searches] - ss = list() - for n, s in self._searches: - ss.append((n, ' %d: re.compile(%r)' % (n, s.pattern))) - ss.append((-1, 'searcher_re:')) - if self.eof_index >= 0: - ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) - if self.timeout_index >= 0: - ss.append((self.timeout_index, ' %d: TIMEOUT' % - self.timeout_index)) - ss.sort() - ss = list(zip(*ss))[1] - return '\n'.join(ss) - - def search(self, buffer, freshlen, searchwindowsize=None): - '''This searches 'buffer' for the first occurrence of one of the regular - expressions. 'freshlen' must indicate the number of bytes at the end of - 'buffer' which have not been searched before. - - See class spawn for the 'searchwindowsize' argument. - - If there is a match this returns the index of that string, and sets - 'start', 'end' and 'match'. Otherwise, returns -1.''' - - first_match = None - # 'freshlen' doesn't help here -- we cannot predict the - # length of a match, and the re module provides no help. - if searchwindowsize is None: - searchstart = 0 - else: - searchstart = max(0, len(buffer) - searchwindowsize) - for index, s in self._searches: - match = s.search(buffer, searchstart) - if match is None: - continue - n = match.start() - if first_match is None or n < first_match: - first_match = n - the_match = match - best_index = index - if first_match is None: - return -1 - self.start = first_match - self.match = the_match - self.end = self.match.end() - return best_index diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py deleted file mode 100644 index cddd50e10058..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py +++ /dev/null @@ -1,148 +0,0 @@ -'''This is like pexpect, but it will work with any file descriptor that you -pass it. You are responsible for opening and close the file descriptor. -This allows you to use Pexpect with sockets and named pipes (FIFOs). - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -from .spawnbase import SpawnBase -from .exceptions import ExceptionPexpect, TIMEOUT -from .utils import select_ignore_interrupts, poll_ignore_interrupts -import os - -__all__ = ['fdspawn'] - -class fdspawn(SpawnBase): - '''This is like pexpect.spawn but allows you to supply your own open file - descriptor. For example, you could use it to read through a file looking - for patterns, or to control a modem or serial device. ''' - - def __init__ (self, fd, args=None, timeout=30, maxread=2000, searchwindowsize=None, - logfile=None, encoding=None, codec_errors='strict', use_poll=False): - '''This takes a file descriptor (an int) or an object that support the - fileno() method (returning an int). All Python file-like objects - support fileno(). ''' - - if type(fd) != type(0) and hasattr(fd, 'fileno'): - fd = fd.fileno() - - if type(fd) != type(0): - raise ExceptionPexpect('The fd argument is not an int. If this is a command string then maybe you want to use pexpect.spawn.') - - try: # make sure fd is a valid file descriptor - os.fstat(fd) - except OSError: - raise ExceptionPexpect('The fd argument is not a valid file descriptor.') - - self.args = None - self.command = None - SpawnBase.__init__(self, timeout, maxread, searchwindowsize, logfile, - encoding=encoding, codec_errors=codec_errors) - self.child_fd = fd - self.own_fd = False - self.closed = False - self.name = '' % fd - self.use_poll = use_poll - - def close (self): - """Close the file descriptor. - - Calling this method a second time does nothing, but if the file - descriptor was closed elsewhere, :class:`OSError` will be raised. - """ - if self.child_fd == -1: - return - - self.flush() - os.close(self.child_fd) - self.child_fd = -1 - self.closed = True - - def isalive (self): - '''This checks if the file descriptor is still valid. If :func:`os.fstat` - does not raise an exception then we assume it is alive. ''' - - if self.child_fd == -1: - return False - try: - os.fstat(self.child_fd) - return True - except: - return False - - def terminate (self, force=False): # pragma: no cover - '''Deprecated and invalid. Just raises an exception.''' - raise ExceptionPexpect('This method is not valid for file descriptors.') - - # These four methods are left around for backwards compatibility, but not - # documented as part of fdpexpect. You're encouraged to use os.write - # directly. - def send(self, s): - "Write to fd, return number of bytes written" - s = self._coerce_send_string(s) - self._log(s, 'send') - - b = self._encoder.encode(s, final=False) - return os.write(self.child_fd, b) - - def sendline(self, s): - "Write to fd with trailing newline, return number of bytes written" - s = self._coerce_send_string(s) - return self.send(s + self.linesep) - - def write(self, s): - "Write to fd, return None" - self.send(s) - - def writelines(self, sequence): - "Call self.write() for each item in sequence" - for s in sequence: - self.write(s) - - def read_nonblocking(self, size=1, timeout=-1): - """ - Read from the file descriptor and return the result as a string. - - The read_nonblocking method of :class:`SpawnBase` assumes that a call - to os.read will not block (timeout parameter is ignored). This is not - the case for POSIX file-like objects such as sockets and serial ports. - - Use :func:`select.select`, timeout is implemented conditionally for - POSIX systems. - - :param int size: Read at most *size* bytes. - :param int timeout: Wait timeout seconds for file descriptor to be - ready to read. When -1 (default), use self.timeout. When 0, poll. - :return: String containing the bytes read - """ - if os.name == 'posix': - if timeout == -1: - timeout = self.timeout - rlist = [self.child_fd] - wlist = [] - xlist = [] - if self.use_poll: - rlist = poll_ignore_interrupts(rlist, timeout) - else: - rlist, wlist, xlist = select_ignore_interrupts( - rlist, wlist, xlist, timeout - ) - if self.child_fd not in rlist: - raise TIMEOUT('Timeout exceeded.') - return super(fdspawn, self).read_nonblocking(size) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py deleted file mode 100644 index 4bb58cfe76c9..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py +++ /dev/null @@ -1,188 +0,0 @@ -"""Provides an interface like pexpect.spawn interface using subprocess.Popen -""" -import os -import threading -import subprocess -import sys -import time -import signal -import shlex - -try: - from queue import Queue, Empty # Python 3 -except ImportError: - from Queue import Queue, Empty # Python 2 - -from .spawnbase import SpawnBase, PY3 -from .exceptions import EOF -from .utils import string_types - -class PopenSpawn(SpawnBase): - def __init__(self, cmd, timeout=30, maxread=2000, searchwindowsize=None, - logfile=None, cwd=None, env=None, encoding=None, - codec_errors='strict', preexec_fn=None): - super(PopenSpawn, self).__init__(timeout=timeout, maxread=maxread, - searchwindowsize=searchwindowsize, logfile=logfile, - encoding=encoding, codec_errors=codec_errors) - - # Note that `SpawnBase` initializes `self.crlf` to `\r\n` - # because the default behaviour for a PTY is to convert - # incoming LF to `\r\n` (see the `onlcr` flag and - # https://stackoverflow.com/a/35887657/5397009). Here we set - # it to `os.linesep` because that is what the spawned - # application outputs by default and `popen` doesn't translate - # anything. - if encoding is None: - self.crlf = os.linesep.encode ("ascii") - else: - self.crlf = self.string_type (os.linesep) - - kwargs = dict(bufsize=0, stdin=subprocess.PIPE, - stderr=subprocess.STDOUT, stdout=subprocess.PIPE, - cwd=cwd, preexec_fn=preexec_fn, env=env) - - if sys.platform == 'win32': - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - kwargs['startupinfo'] = startupinfo - kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP - - if isinstance(cmd, string_types) and sys.platform != 'win32': - cmd = shlex.split(cmd, posix=os.name == 'posix') - - self.proc = subprocess.Popen(cmd, **kwargs) - self.pid = self.proc.pid - self.closed = False - self._buf = self.string_type() - - self._read_queue = Queue() - self._read_thread = threading.Thread(target=self._read_incoming) - self._read_thread.setDaemon(True) - self._read_thread.start() - - _read_reached_eof = False - - def read_nonblocking(self, size, timeout): - buf = self._buf - if self._read_reached_eof: - # We have already finished reading. Use up any buffered data, - # then raise EOF - if buf: - self._buf = buf[size:] - return buf[:size] - else: - self.flag_eof = True - raise EOF('End Of File (EOF).') - - if timeout == -1: - timeout = self.timeout - elif timeout is None: - timeout = 1e6 - - t0 = time.time() - while (time.time() - t0) < timeout and size and len(buf) < size: - try: - incoming = self._read_queue.get_nowait() - except Empty: - break - else: - if incoming is None: - self._read_reached_eof = True - break - - buf += self._decoder.decode(incoming, final=False) - - r, self._buf = buf[:size], buf[size:] - - self._log(r, 'read') - return r - - def _read_incoming(self): - """Run in a thread to move output from a pipe to a queue.""" - fileno = self.proc.stdout.fileno() - while 1: - buf = b'' - try: - buf = os.read(fileno, 1024) - except OSError as e: - self._log(e, 'read') - - if not buf: - # This indicates we have reached EOF - self._read_queue.put(None) - return - - self._read_queue.put(buf) - - def write(self, s): - '''This is similar to send() except that there is no return value. - ''' - self.send(s) - - def writelines(self, sequence): - '''This calls write() for each element in the sequence. - - The sequence can be any iterable object producing strings, typically a - list of strings. This does not add line separators. There is no return - value. - ''' - for s in sequence: - self.send(s) - - def send(self, s): - '''Send data to the subprocess' stdin. - - Returns the number of bytes written. - ''' - s = self._coerce_send_string(s) - self._log(s, 'send') - - b = self._encoder.encode(s, final=False) - if PY3: - return self.proc.stdin.write(b) - else: - # On Python 2, .write() returns None, so we return the length of - # bytes written ourselves. This assumes they all got written. - self.proc.stdin.write(b) - return len(b) - - def sendline(self, s=''): - '''Wraps send(), sending string ``s`` to child process, with os.linesep - automatically appended. Returns number of bytes written. ''' - - n = self.send(s) - return n + self.send(self.linesep) - - def wait(self): - '''Wait for the subprocess to finish. - - Returns the exit code. - ''' - status = self.proc.wait() - if status >= 0: - self.exitstatus = status - self.signalstatus = None - else: - self.exitstatus = None - self.signalstatus = -status - self.terminated = True - return status - - def kill(self, sig): - '''Sends a Unix signal to the subprocess. - - Use constants from the :mod:`signal` module to specify which signal. - ''' - if sys.platform == 'win32': - if sig in [signal.SIGINT, signal.CTRL_C_EVENT]: - sig = signal.CTRL_C_EVENT - elif sig in [signal.SIGBREAK, signal.CTRL_BREAK_EVENT]: - sig = signal.CTRL_BREAK_EVENT - else: - sig = signal.SIGTERM - - os.kill(self.proc.pid, sig) - - def sendeof(self): - '''Closes the stdin pipe from the writing end.''' - self.proc.stdin.close() diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py deleted file mode 100644 index 6b9ad3f63f7c..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py +++ /dev/null @@ -1,833 +0,0 @@ -import os -import sys -import time -import pty -import tty -import errno -import signal -from contextlib import contextmanager - -import ptyprocess -from ptyprocess.ptyprocess import use_native_pty_fork - -from .exceptions import ExceptionPexpect, EOF, TIMEOUT -from .spawnbase import SpawnBase -from .utils import ( - which, split_command_line, select_ignore_interrupts, poll_ignore_interrupts -) - -@contextmanager -def _wrap_ptyprocess_err(): - """Turn ptyprocess errors into our own ExceptionPexpect errors""" - try: - yield - except ptyprocess.PtyProcessError as e: - raise ExceptionPexpect(*e.args) - -PY3 = (sys.version_info[0] >= 3) - -class spawn(SpawnBase): - '''This is the main class interface for Pexpect. Use this class to start - and control child applications. ''' - - # This is purely informational now - changing it has no effect - use_native_pty_fork = use_native_pty_fork - - def __init__(self, command, args=[], timeout=30, maxread=2000, - searchwindowsize=None, logfile=None, cwd=None, env=None, - ignore_sighup=False, echo=True, preexec_fn=None, - encoding=None, codec_errors='strict', dimensions=None, - use_poll=False): - '''This is the constructor. The command parameter may be a string that - includes a command and any arguments to the command. For example:: - - child = pexpect.spawn('/usr/bin/ftp') - child = pexpect.spawn('/usr/bin/ssh user@example.com') - child = pexpect.spawn('ls -latr /tmp') - - You may also construct it with a list of arguments like so:: - - child = pexpect.spawn('/usr/bin/ftp', []) - child = pexpect.spawn('/usr/bin/ssh', ['user@example.com']) - child = pexpect.spawn('ls', ['-latr', '/tmp']) - - After this the child application will be created and will be ready to - talk to. For normal use, see expect() and send() and sendline(). - - Remember that Pexpect does NOT interpret shell meta characters such as - redirect, pipe, or wild cards (``>``, ``|``, or ``*``). This is a - common mistake. If you want to run a command and pipe it through - another command then you must also start a shell. For example:: - - child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"') - child.expect(pexpect.EOF) - - The second form of spawn (where you pass a list of arguments) is useful - in situations where you wish to spawn a command and pass it its own - argument list. This can make syntax more clear. For example, the - following is equivalent to the previous example:: - - shell_cmd = 'ls -l | grep LOG > logs.txt' - child = pexpect.spawn('/bin/bash', ['-c', shell_cmd]) - child.expect(pexpect.EOF) - - The maxread attribute sets the read buffer size. This is maximum number - of bytes that Pexpect will try to read from a TTY at one time. Setting - the maxread size to 1 will turn off buffering. Setting the maxread - value higher may help performance in cases where large amounts of - output are read back from the child. This feature is useful in - conjunction with searchwindowsize. - - When the keyword argument *searchwindowsize* is None (default), the - full buffer is searched at each iteration of receiving incoming data. - The default number of bytes scanned at each iteration is very large - and may be reduced to collaterally reduce search cost. After - :meth:`~.expect` returns, the full buffer attribute remains up to - size *maxread* irrespective of *searchwindowsize* value. - - When the keyword argument ``timeout`` is specified as a number, - (default: *30*), then :class:`TIMEOUT` will be raised after the value - specified has elapsed, in seconds, for any of the :meth:`~.expect` - family of method calls. When None, TIMEOUT will not be raised, and - :meth:`~.expect` may block indefinitely until match. - - - The logfile member turns on or off logging. All input and output will - be copied to the given file object. Set logfile to None to stop - logging. This is the default. Set logfile to sys.stdout to echo - everything to standard output. The logfile is flushed after each write. - - Example log input and output to a file:: - - child = pexpect.spawn('some_command') - fout = open('mylog.txt','wb') - child.logfile = fout - - Example log to stdout:: - - # In Python 2: - child = pexpect.spawn('some_command') - child.logfile = sys.stdout - - # In Python 3, we'll use the ``encoding`` argument to decode data - # from the subprocess and handle it as unicode: - child = pexpect.spawn('some_command', encoding='utf-8') - child.logfile = sys.stdout - - The logfile_read and logfile_send members can be used to separately log - the input from the child and output sent to the child. Sometimes you - don't want to see everything you write to the child. You only want to - log what the child sends back. For example:: - - child = pexpect.spawn('some_command') - child.logfile_read = sys.stdout - - You will need to pass an encoding to spawn in the above code if you are - using Python 3. - - To separately log output sent to the child use logfile_send:: - - child.logfile_send = fout - - If ``ignore_sighup`` is True, the child process will ignore SIGHUP - signals. The default is False from Pexpect 4.0, meaning that SIGHUP - will be handled normally by the child. - - The delaybeforesend helps overcome a weird behavior that many users - were experiencing. The typical problem was that a user would expect() a - "Password:" prompt and then immediately call sendline() to send the - password. The user would then see that their password was echoed back - to them. Passwords don't normally echo. The problem is caused by the - fact that most applications print out the "Password" prompt and then - turn off stdin echo, but if you send your password before the - application turned off echo, then you get your password echoed. - Normally this wouldn't be a problem when interacting with a human at a - real keyboard. If you introduce a slight delay just before writing then - this seems to clear up the problem. This was such a common problem for - many users that I decided that the default pexpect behavior should be - to sleep just before writing to the child application. 1/20th of a - second (50 ms) seems to be enough to clear up the problem. You can set - delaybeforesend to None to return to the old behavior. - - Note that spawn is clever about finding commands on your path. - It uses the same logic that "which" uses to find executables. - - If you wish to get the exit status of the child you must call the - close() method. The exit or signal status of the child will be stored - in self.exitstatus or self.signalstatus. If the child exited normally - then exitstatus will store the exit return code and signalstatus will - be None. If the child was terminated abnormally with a signal then - signalstatus will store the signal value and exitstatus will be None:: - - child = pexpect.spawn('some_command') - child.close() - print(child.exitstatus, child.signalstatus) - - If you need more detail you can also read the self.status member which - stores the status returned by os.waitpid. You can interpret this using - os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. - - The echo attribute may be set to False to disable echoing of input. - As a pseudo-terminal, all input echoed by the "keyboard" (send() - or sendline()) will be repeated to output. For many cases, it is - not desirable to have echo enabled, and it may be later disabled - using setecho(False) followed by waitnoecho(). However, for some - platforms such as Solaris, this is not possible, and should be - disabled immediately on spawn. - - If preexec_fn is given, it will be called in the child process before - launching the given command. This is useful to e.g. reset inherited - signal handlers. - - The dimensions attribute specifies the size of the pseudo-terminal as - seen by the subprocess, and is specified as a two-entry tuple (rows, - columns). If this is unspecified, the defaults in ptyprocess will apply. - - The use_poll attribute enables using select.poll() over select.select() - for socket handling. This is handy if your system could have > 1024 fds - ''' - super(spawn, self).__init__(timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, - logfile=logfile, encoding=encoding, codec_errors=codec_errors) - self.STDIN_FILENO = pty.STDIN_FILENO - self.STDOUT_FILENO = pty.STDOUT_FILENO - self.STDERR_FILENO = pty.STDERR_FILENO - self.cwd = cwd - self.env = env - self.echo = echo - self.ignore_sighup = ignore_sighup - self.__irix_hack = sys.platform.lower().startswith('irix') - if command is None: - self.command = None - self.args = None - self.name = '' - else: - self._spawn(command, args, preexec_fn, dimensions) - self.use_poll = use_poll - - def __str__(self): - '''This returns a human-readable string that represents the state of - the object. ''' - - s = [] - s.append(repr(self)) - s.append('command: ' + str(self.command)) - s.append('args: %r' % (self.args,)) - s.append('buffer (last 100 chars): %r' % self.buffer[-100:]) - s.append('before (last 100 chars): %r' % self.before[-100:] if self.before else '') - s.append('after: %r' % (self.after,)) - s.append('match: %r' % (self.match,)) - s.append('match_index: ' + str(self.match_index)) - s.append('exitstatus: ' + str(self.exitstatus)) - if hasattr(self, 'ptyproc'): - s.append('flag_eof: ' + str(self.flag_eof)) - s.append('pid: ' + str(self.pid)) - s.append('child_fd: ' + str(self.child_fd)) - s.append('closed: ' + str(self.closed)) - s.append('timeout: ' + str(self.timeout)) - s.append('delimiter: ' + str(self.delimiter)) - s.append('logfile: ' + str(self.logfile)) - s.append('logfile_read: ' + str(self.logfile_read)) - s.append('logfile_send: ' + str(self.logfile_send)) - s.append('maxread: ' + str(self.maxread)) - s.append('ignorecase: ' + str(self.ignorecase)) - s.append('searchwindowsize: ' + str(self.searchwindowsize)) - s.append('delaybeforesend: ' + str(self.delaybeforesend)) - s.append('delayafterclose: ' + str(self.delayafterclose)) - s.append('delayafterterminate: ' + str(self.delayafterterminate)) - return '\n'.join(s) - - def _spawn(self, command, args=[], preexec_fn=None, dimensions=None): - '''This starts the given command in a child process. This does all the - fork/exec type of stuff for a pty. This is called by __init__. If args - is empty then command will be parsed (split on spaces) and args will be - set to parsed arguments. ''' - - # The pid and child_fd of this object get set by this method. - # Note that it is difficult for this method to fail. - # You cannot detect if the child process cannot start. - # So the only way you can tell if the child process started - # or not is to try to read from the file descriptor. If you get - # EOF immediately then it means that the child is already dead. - # That may not necessarily be bad because you may have spawned a child - # that performs some task; creates no stdout output; and then dies. - - # If command is an int type then it may represent a file descriptor. - if isinstance(command, type(0)): - raise ExceptionPexpect('Command is an int type. ' + - 'If this is a file descriptor then maybe you want to ' + - 'use fdpexpect.fdspawn which takes an existing ' + - 'file descriptor instead of a command string.') - - if not isinstance(args, type([])): - raise TypeError('The argument, args, must be a list.') - - if args == []: - self.args = split_command_line(command) - self.command = self.args[0] - else: - # Make a shallow copy of the args list. - self.args = args[:] - self.args.insert(0, command) - self.command = command - - command_with_path = which(self.command, env=self.env) - if command_with_path is None: - raise ExceptionPexpect('The command was not found or was not ' + - 'executable: %s.' % self.command) - self.command = command_with_path - self.args[0] = self.command - - self.name = '<' + ' '.join(self.args) + '>' - - assert self.pid is None, 'The pid member must be None.' - assert self.command is not None, 'The command member must not be None.' - - kwargs = {'echo': self.echo, 'preexec_fn': preexec_fn} - if self.ignore_sighup: - def preexec_wrapper(): - "Set SIGHUP to be ignored, then call the real preexec_fn" - signal.signal(signal.SIGHUP, signal.SIG_IGN) - if preexec_fn is not None: - preexec_fn() - kwargs['preexec_fn'] = preexec_wrapper - - if dimensions is not None: - kwargs['dimensions'] = dimensions - - if self.encoding is not None: - # Encode command line using the specified encoding - self.args = [a if isinstance(a, bytes) else a.encode(self.encoding) - for a in self.args] - - self.ptyproc = self._spawnpty(self.args, env=self.env, - cwd=self.cwd, **kwargs) - - self.pid = self.ptyproc.pid - self.child_fd = self.ptyproc.fd - - - self.terminated = False - self.closed = False - - def _spawnpty(self, args, **kwargs): - '''Spawn a pty and return an instance of PtyProcess.''' - return ptyprocess.PtyProcess.spawn(args, **kwargs) - - def close(self, force=True): - '''This closes the connection with the child application. Note that - calling close() more than once is valid. This emulates standard Python - behavior with files. Set force to True if you want to make sure that - the child is terminated (SIGKILL is sent if the child ignores SIGHUP - and SIGINT). ''' - - self.flush() - with _wrap_ptyprocess_err(): - # PtyProcessError may be raised if it is not possible to terminate - # the child. - self.ptyproc.close(force=force) - self.isalive() # Update exit status from ptyproc - self.child_fd = -1 - self.closed = True - - def isatty(self): - '''This returns True if the file descriptor is open and connected to a - tty(-like) device, else False. - - On SVR4-style platforms implementing streams, such as SunOS and HP-UX, - the child pty may not appear as a terminal device. This means - methods such as setecho(), setwinsize(), getwinsize() may raise an - IOError. ''' - - return os.isatty(self.child_fd) - - def waitnoecho(self, timeout=-1): - '''This waits until the terminal ECHO flag is set False. This returns - True if the echo mode is off. This returns False if the ECHO flag was - not set False before the timeout. This can be used to detect when the - child is waiting for a password. Usually a child application will turn - off echo mode when it is waiting for the user to enter a password. For - example, instead of expecting the "password:" prompt you can wait for - the child to set ECHO off:: - - p = pexpect.spawn('ssh user@example.com') - p.waitnoecho() - p.sendline(mypassword) - - If timeout==-1 then this method will use the value in self.timeout. - If timeout==None then this method to block until ECHO flag is False. - ''' - - if timeout == -1: - timeout = self.timeout - if timeout is not None: - end_time = time.time() + timeout - while True: - if not self.getecho(): - return True - if timeout < 0 and timeout is not None: - return False - if timeout is not None: - timeout = end_time - time.time() - time.sleep(0.1) - - def getecho(self): - '''This returns the terminal echo mode. This returns True if echo is - on or False if echo is off. Child applications that are expecting you - to enter a password often set ECHO False. See waitnoecho(). - - Not supported on platforms where ``isatty()`` returns False. ''' - return self.ptyproc.getecho() - - def setecho(self, state): - '''This sets the terminal echo mode on or off. Note that anything the - child sent before the echo will be lost, so you should be sure that - your input buffer is empty before you call setecho(). For example, the - following will work as expected:: - - p = pexpect.spawn('cat') # Echo is on by default. - p.sendline('1234') # We expect see this twice from the child... - p.expect(['1234']) # ... once from the tty echo... - p.expect(['1234']) # ... and again from cat itself. - p.setecho(False) # Turn off tty echo - p.sendline('abcd') # We will set this only once (echoed by cat). - p.sendline('wxyz') # We will set this only once (echoed by cat) - p.expect(['abcd']) - p.expect(['wxyz']) - - The following WILL NOT WORK because the lines sent before the setecho - will be lost:: - - p = pexpect.spawn('cat') - p.sendline('1234') - p.setecho(False) # Turn off tty echo - p.sendline('abcd') # We will set this only once (echoed by cat). - p.sendline('wxyz') # We will set this only once (echoed by cat) - p.expect(['1234']) - p.expect(['1234']) - p.expect(['abcd']) - p.expect(['wxyz']) - - - Not supported on platforms where ``isatty()`` returns False. - ''' - return self.ptyproc.setecho(state) - - def read_nonblocking(self, size=1, timeout=-1): - '''This reads at most size characters from the child application. It - includes a timeout. If the read does not complete within the timeout - period then a TIMEOUT exception is raised. If the end of file is read - then an EOF exception will be raised. If a logfile is specified, a - copy is written to that log. - - If timeout is None then the read may block indefinitely. - If timeout is -1 then the self.timeout value is used. If timeout is 0 - then the child is polled and if there is no data immediately ready - then this will raise a TIMEOUT exception. - - The timeout refers only to the amount of time to read at least one - character. This is not affected by the 'size' parameter, so if you call - read_nonblocking(size=100, timeout=30) and only one character is - available right away then one character will be returned immediately. - It will not wait for 30 seconds for another 99 characters to come in. - - This is a wrapper around os.read(). It uses select.select() to - implement the timeout. ''' - - if self.closed: - raise ValueError('I/O operation on closed file.') - - if timeout == -1: - timeout = self.timeout - - # Note that some systems such as Solaris do not give an EOF when - # the child dies. In fact, you can still try to read - # from the child_fd -- it will block forever or until TIMEOUT. - # For this case, I test isalive() before doing any reading. - # If isalive() is false, then I pretend that this is the same as EOF. - if not self.isalive(): - # timeout of 0 means "poll" - if self.use_poll: - r = poll_ignore_interrupts([self.child_fd], timeout) - else: - r, w, e = select_ignore_interrupts([self.child_fd], [], [], 0) - if not r: - self.flag_eof = True - raise EOF('End Of File (EOF). Braindead platform.') - elif self.__irix_hack: - # Irix takes a long time before it realizes a child was terminated. - # FIXME So does this mean Irix systems are forced to always have - # FIXME a 2 second delay when calling read_nonblocking? That sucks. - if self.use_poll: - r = poll_ignore_interrupts([self.child_fd], timeout) - else: - r, w, e = select_ignore_interrupts([self.child_fd], [], [], 2) - if not r and not self.isalive(): - self.flag_eof = True - raise EOF('End Of File (EOF). Slow platform.') - if self.use_poll: - r = poll_ignore_interrupts([self.child_fd], timeout) - else: - r, w, e = select_ignore_interrupts( - [self.child_fd], [], [], timeout - ) - - if not r: - if not self.isalive(): - # Some platforms, such as Irix, will claim that their - # processes are alive; timeout on the select; and - # then finally admit that they are not alive. - self.flag_eof = True - raise EOF('End of File (EOF). Very slow platform.') - else: - raise TIMEOUT('Timeout exceeded.') - - if self.child_fd in r: - return super(spawn, self).read_nonblocking(size) - - raise ExceptionPexpect('Reached an unexpected state.') # pragma: no cover - - def write(self, s): - '''This is similar to send() except that there is no return value. - ''' - - self.send(s) - - def writelines(self, sequence): - '''This calls write() for each element in the sequence. The sequence - can be any iterable object producing strings, typically a list of - strings. This does not add line separators. There is no return value. - ''' - - for s in sequence: - self.write(s) - - def send(self, s): - '''Sends string ``s`` to the child process, returning the number of - bytes written. If a logfile is specified, a copy is written to that - log. - - The default terminal input mode is canonical processing unless set - otherwise by the child process. This allows backspace and other line - processing to be performed prior to transmitting to the receiving - program. As this is buffered, there is a limited size of such buffer. - - On Linux systems, this is 4096 (defined by N_TTY_BUF_SIZE). All - other systems honor the POSIX.1 definition PC_MAX_CANON -- 1024 - on OSX, 256 on OpenSolaris, and 1920 on FreeBSD. - - This value may be discovered using fpathconf(3):: - - >>> from os import fpathconf - >>> print(fpathconf(0, 'PC_MAX_CANON')) - 256 - - On such a system, only 256 bytes may be received per line. Any - subsequent bytes received will be discarded. BEL (``'\a'``) is then - sent to output if IMAXBEL (termios.h) is set by the tty driver. - This is usually enabled by default. Linux does not honor this as - an option -- it behaves as though it is always set on. - - Canonical input processing may be disabled altogether by executing - a shell, then stty(1), before executing the final program:: - - >>> bash = pexpect.spawn('/bin/bash', echo=False) - >>> bash.sendline('stty -icanon') - >>> bash.sendline('base64') - >>> bash.sendline('x' * 5000) - ''' - - if self.delaybeforesend is not None: - time.sleep(self.delaybeforesend) - - s = self._coerce_send_string(s) - self._log(s, 'send') - - b = self._encoder.encode(s, final=False) - return os.write(self.child_fd, b) - - def sendline(self, s=''): - '''Wraps send(), sending string ``s`` to child process, with - ``os.linesep`` automatically appended. Returns number of bytes - written. Only a limited number of bytes may be sent for each - line in the default terminal mode, see docstring of :meth:`send`. - ''' - s = self._coerce_send_string(s) - return self.send(s + self.linesep) - - def _log_control(self, s): - """Write control characters to the appropriate log files""" - if self.encoding is not None: - s = s.decode(self.encoding, 'replace') - self._log(s, 'send') - - def sendcontrol(self, char): - '''Helper method that wraps send() with mnemonic access for sending control - character to the child (such as Ctrl-C or Ctrl-D). For example, to send - Ctrl-G (ASCII 7, bell, '\a'):: - - child.sendcontrol('g') - - See also, sendintr() and sendeof(). - ''' - n, byte = self.ptyproc.sendcontrol(char) - self._log_control(byte) - return n - - def sendeof(self): - '''This sends an EOF to the child. This sends a character which causes - the pending parent output buffer to be sent to the waiting child - program without waiting for end-of-line. If it is the first character - of the line, the read() in the user program returns 0, which signifies - end-of-file. This means to work as expected a sendeof() has to be - called at the beginning of a line. This method does not send a newline. - It is the responsibility of the caller to ensure the eof is sent at the - beginning of a line. ''' - - n, byte = self.ptyproc.sendeof() - self._log_control(byte) - - def sendintr(self): - '''This sends a SIGINT to the child. It does not require - the SIGINT to be the first character on a line. ''' - - n, byte = self.ptyproc.sendintr() - self._log_control(byte) - - @property - def flag_eof(self): - return self.ptyproc.flag_eof - - @flag_eof.setter - def flag_eof(self, value): - self.ptyproc.flag_eof = value - - def eof(self): - '''This returns True if the EOF exception was ever raised. - ''' - return self.flag_eof - - def terminate(self, force=False): - '''This forces a child process to terminate. It starts nicely with - SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This - returns True if the child was terminated. This returns False if the - child could not be terminated. ''' - - if not self.isalive(): - return True - try: - self.kill(signal.SIGHUP) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - self.kill(signal.SIGCONT) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - self.kill(signal.SIGINT) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - if force: - self.kill(signal.SIGKILL) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - else: - return False - return False - except OSError: - # I think there are kernel timing issues that sometimes cause - # this to happen. I think isalive() reports True, but the - # process is dead to the kernel. - # Make one last attempt to see if the kernel is up to date. - time.sleep(self.delayafterterminate * 10) - if not self.isalive(): - return True - else: - return False - - def wait(self): - '''This waits until the child exits. This is a blocking call. This will - not read any data from the child, so this will block forever if the - child has unread output and has terminated. In other words, the child - may have printed output then called exit(), but, the child is - technically still alive until its output is read by the parent. - - This method is non-blocking if :meth:`wait` has already been called - previously or :meth:`isalive` method returns False. It simply returns - the previously determined exit status. - ''' - - ptyproc = self.ptyproc - with _wrap_ptyprocess_err(): - # exception may occur if "Is some other process attempting - # "job control with our child pid?" - exitstatus = ptyproc.wait() - self.status = ptyproc.status - self.exitstatus = ptyproc.exitstatus - self.signalstatus = ptyproc.signalstatus - self.terminated = True - - return exitstatus - - def isalive(self): - '''This tests if the child process is running or not. This is - non-blocking. If the child was terminated then this will read the - exitstatus or signalstatus of the child. This returns True if the child - process appears to be running or False if not. It can take literally - SECONDS for Solaris to return the right status. ''' - - ptyproc = self.ptyproc - with _wrap_ptyprocess_err(): - alive = ptyproc.isalive() - - if not alive: - self.status = ptyproc.status - self.exitstatus = ptyproc.exitstatus - self.signalstatus = ptyproc.signalstatus - self.terminated = True - - return alive - - def kill(self, sig): - - '''This sends the given signal to the child application. In keeping - with UNIX tradition it has a misleading name. It does not necessarily - kill the child unless you send the right signal. ''' - - # Same as os.kill, but the pid is given for you. - if self.isalive(): - os.kill(self.pid, sig) - - def getwinsize(self): - '''This returns the terminal window size of the child tty. The return - value is a tuple of (rows, cols). ''' - return self.ptyproc.getwinsize() - - def setwinsize(self, rows, cols): - '''This sets the terminal window size of the child tty. This will cause - a SIGWINCH signal to be sent to the child. This does not change the - physical window size. It changes the size reported to TTY-aware - applications like vi or curses -- applications that respond to the - SIGWINCH signal. ''' - return self.ptyproc.setwinsize(rows, cols) - - - def interact(self, escape_character=chr(29), - input_filter=None, output_filter=None): - - '''This gives control of the child process to the interactive user (the - human at the keyboard). Keystrokes are sent to the child process, and - the stdout and stderr output of the child process is printed. This - simply echos the child stdout and child stderr to the real stdout and - it echos the real stdin to the child stdin. When the user types the - escape_character this method will return None. The escape_character - will not be transmitted. The default for escape_character is - entered as ``Ctrl - ]``, the very same as BSD telnet. To prevent - escaping, escape_character may be set to None. - - If a logfile is specified, then the data sent and received from the - child process in interact mode is duplicated to the given log. - - You may pass in optional input and output filter functions. These - functions should take a string and return a string. The output_filter - will be passed all the output from the child process. The input_filter - will be passed all the keyboard input from the user. The input_filter - is run BEFORE the check for the escape_character. - - Note that if you change the window size of the parent the SIGWINCH - signal will not be passed through to the child. If you want the child - window size to change when the parent's window size changes then do - something like the following example:: - - import pexpect, struct, fcntl, termios, signal, sys - def sigwinch_passthrough (sig, data): - s = struct.pack("HHHH", 0, 0, 0, 0) - a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), - termios.TIOCGWINSZ , s)) - if not p.closed: - p.setwinsize(a[0],a[1]) - - # Note this 'p' is global and used in sigwinch_passthrough. - p = pexpect.spawn('/bin/bash') - signal.signal(signal.SIGWINCH, sigwinch_passthrough) - p.interact() - ''' - - # Flush the buffer. - self.write_to_stdout(self.buffer) - self.stdout.flush() - self._buffer = self.buffer_type() - mode = tty.tcgetattr(self.STDIN_FILENO) - tty.setraw(self.STDIN_FILENO) - if escape_character is not None and PY3: - escape_character = escape_character.encode('latin-1') - try: - self.__interact_copy(escape_character, input_filter, output_filter) - finally: - tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode) - - def __interact_writen(self, fd, data): - '''This is used by the interact() method. - ''' - - while data != b'' and self.isalive(): - n = os.write(fd, data) - data = data[n:] - - def __interact_read(self, fd): - '''This is used by the interact() method. - ''' - - return os.read(fd, 1000) - - def __interact_copy( - self, escape_character=None, input_filter=None, output_filter=None - ): - - '''This is used by the interact() method. - ''' - - while self.isalive(): - if self.use_poll: - r = poll_ignore_interrupts([self.child_fd, self.STDIN_FILENO]) - else: - r, w, e = select_ignore_interrupts( - [self.child_fd, self.STDIN_FILENO], [], [] - ) - if self.child_fd in r: - try: - data = self.__interact_read(self.child_fd) - except OSError as err: - if err.args[0] == errno.EIO: - # Linux-style EOF - break - raise - if data == b'': - # BSD-style EOF - break - if output_filter: - data = output_filter(data) - self._log(data, 'read') - os.write(self.STDOUT_FILENO, data) - if self.STDIN_FILENO in r: - data = self.__interact_read(self.STDIN_FILENO) - if input_filter: - data = input_filter(data) - i = -1 - if escape_character is not None: - i = data.rfind(escape_character) - if i != -1: - data = data[:i] - if data: - self._log(data, 'send') - self.__interact_writen(self.child_fd, data) - break - self._log(data, 'send') - self.__interact_writen(self.child_fd, data) - - -def spawnu(*args, **kwargs): - """Deprecated: pass encoding to spawn() instead.""" - kwargs.setdefault('encoding', 'utf-8') - return spawn(*args, **kwargs) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py deleted file mode 100644 index ef2e91186b37..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/pxssh.py +++ /dev/null @@ -1,499 +0,0 @@ -'''This class extends pexpect.spawn to specialize setting up SSH connections. -This adds methods for login, logout, and expecting the shell prompt. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn -import time -import os -import sys -import re - -__all__ = ['ExceptionPxssh', 'pxssh'] - -# Exception classes used by this module. -class ExceptionPxssh(ExceptionPexpect): - '''Raised for pxssh exceptions. - ''' - -if sys.version_info > (3, 0): - from shlex import quote -else: - _find_unsafe = re.compile(r'[^\w@%+=:,./-]').search - - def quote(s): - """Return a shell-escaped version of the string *s*.""" - if not s: - return "''" - if _find_unsafe(s) is None: - return s - - # use single quotes, and put single quotes into double quotes - # the string $'b is then quoted as '$'"'"'b' - return "'" + s.replace("'", "'\"'\"'") + "'" - -class pxssh (spawn): - '''This class extends pexpect.spawn to specialize setting up SSH - connections. This adds methods for login, logout, and expecting the shell - prompt. It does various tricky things to handle many situations in the SSH - login process. For example, if the session is your first login, then pxssh - automatically accepts the remote certificate; or if you have public key - authentication setup then pxssh won't wait for the password prompt. - - pxssh uses the shell prompt to synchronize output from the remote host. In - order to make this more robust it sets the shell prompt to something more - unique than just $ or #. This should work on most Borne/Bash or Csh style - shells. - - Example that runs a few commands on a remote server and prints the result:: - - from pexpect import pxssh - import getpass - try: - s = pxssh.pxssh() - hostname = raw_input('hostname: ') - username = raw_input('username: ') - password = getpass.getpass('password: ') - s.login(hostname, username, password) - s.sendline('uptime') # run a command - s.prompt() # match the prompt - print(s.before) # print everything before the prompt. - s.sendline('ls -l') - s.prompt() - print(s.before) - s.sendline('df') - s.prompt() - print(s.before) - s.logout() - except pxssh.ExceptionPxssh as e: - print("pxssh failed on login.") - print(e) - - Example showing how to specify SSH options:: - - from pexpect import pxssh - s = pxssh.pxssh(options={ - "StrictHostKeyChecking": "no", - "UserKnownHostsFile": "/dev/null"}) - ... - - Note that if you have ssh-agent running while doing development with pxssh - then this can lead to a lot of confusion. Many X display managers (xdm, - gdm, kdm, etc.) will automatically start a GUI agent. You may see a GUI - dialog box popup asking for a password during development. You should turn - off any key agents during testing. The 'force_password' attribute will turn - off public key authentication. This will only work if the remote SSH server - is configured to allow password logins. Example of using 'force_password' - attribute:: - - s = pxssh.pxssh() - s.force_password = True - hostname = raw_input('hostname: ') - username = raw_input('username: ') - password = getpass.getpass('password: ') - s.login (hostname, username, password) - - `debug_command_string` is only for the test suite to confirm that the string - generated for SSH is correct, using this will not allow you to do - anything other than get a string back from `pxssh.pxssh.login()`. - ''' - - def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None, - logfile=None, cwd=None, env=None, ignore_sighup=True, echo=True, - options={}, encoding=None, codec_errors='strict', - debug_command_string=False): - - spawn.__init__(self, None, timeout=timeout, maxread=maxread, - searchwindowsize=searchwindowsize, logfile=logfile, - cwd=cwd, env=env, ignore_sighup=ignore_sighup, echo=echo, - encoding=encoding, codec_errors=codec_errors) - - self.name = '' - - #SUBTLE HACK ALERT! Note that the command that SETS the prompt uses a - #slightly different string than the regular expression to match it. This - #is because when you set the prompt the command will echo back, but we - #don't want to match the echoed command. So if we make the set command - #slightly different than the regex we eliminate the problem. To make the - #set command different we add a backslash in front of $. The $ doesn't - #need to be escaped, but it doesn't hurt and serves to make the set - #prompt command different than the regex. - - # used to match the command-line prompt - self.UNIQUE_PROMPT = r"\[PEXPECT\][\$\#] " - self.PROMPT = self.UNIQUE_PROMPT - - # used to set shell command-line prompt to UNIQUE_PROMPT. - self.PROMPT_SET_SH = r"PS1='[PEXPECT]\$ '" - self.PROMPT_SET_CSH = r"set prompt='[PEXPECT]\$ '" - self.SSH_OPTS = ("-o'RSAAuthentication=no'" - + " -o 'PubkeyAuthentication=no'") -# Disabling host key checking, makes you vulnerable to MITM attacks. -# + " -o 'StrictHostKeyChecking=no'" -# + " -o 'UserKnownHostsFile /dev/null' ") - # Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from - # displaying a GUI password dialog. I have not figured out how to - # disable only SSH_ASKPASS without also disabling X11 forwarding. - # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying! - #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'" - self.force_password = False - - self.debug_command_string = debug_command_string - - # User defined SSH options, eg, - # ssh.otions = dict(StrictHostKeyChecking="no",UserKnownHostsFile="/dev/null") - self.options = options - - def levenshtein_distance(self, a, b): - '''This calculates the Levenshtein distance between a and b. - ''' - - n, m = len(a), len(b) - if n > m: - a,b = b,a - n,m = m,n - current = range(n+1) - for i in range(1,m+1): - previous, current = current, [i]+[0]*n - for j in range(1,n+1): - add, delete = previous[j]+1, current[j-1]+1 - change = previous[j-1] - if a[j-1] != b[i-1]: - change = change + 1 - current[j] = min(add, delete, change) - return current[n] - - def try_read_prompt(self, timeout_multiplier): - '''This facilitates using communication timeouts to perform - synchronization as quickly as possible, while supporting high latency - connections with a tunable worst case performance. Fast connections - should be read almost immediately. Worst case performance for this - method is timeout_multiplier * 3 seconds. - ''' - - # maximum time allowed to read the first response - first_char_timeout = timeout_multiplier * 0.5 - - # maximum time allowed between subsequent characters - inter_char_timeout = timeout_multiplier * 0.1 - - # maximum time for reading the entire prompt - total_timeout = timeout_multiplier * 3.0 - - prompt = self.string_type() - begin = time.time() - expired = 0.0 - timeout = first_char_timeout - - while expired < total_timeout: - try: - prompt += self.read_nonblocking(size=1, timeout=timeout) - expired = time.time() - begin # updated total time expired - timeout = inter_char_timeout - except TIMEOUT: - break - - return prompt - - def sync_original_prompt (self, sync_multiplier=1.0): - '''This attempts to find the prompt. Basically, press enter and record - the response; press enter again and record the response; if the two - responses are similar then assume we are at the original prompt. - This can be a slow function. Worst case with the default sync_multiplier - can take 12 seconds. Low latency connections are more likely to fail - with a low sync_multiplier. Best case sync time gets worse with a - high sync multiplier (500 ms with default). ''' - - # All of these timing pace values are magic. - # I came up with these based on what seemed reliable for - # connecting to a heavily loaded machine I have. - self.sendline() - time.sleep(0.1) - - try: - # Clear the buffer before getting the prompt. - self.try_read_prompt(sync_multiplier) - except TIMEOUT: - pass - - self.sendline() - x = self.try_read_prompt(sync_multiplier) - - self.sendline() - a = self.try_read_prompt(sync_multiplier) - - self.sendline() - b = self.try_read_prompt(sync_multiplier) - - ld = self.levenshtein_distance(a,b) - len_a = len(a) - if len_a == 0: - return False - if float(ld)/len_a < 0.4: - return True - return False - - ### TODO: This is getting messy and I'm pretty sure this isn't perfect. - ### TODO: I need to draw a flow chart for this. - ### TODO: Unit tests for SSH tunnels, remote SSH command exec, disabling original prompt sync - def login (self, server, username, password='', terminal_type='ansi', - original_prompt=r"[#$]", login_timeout=10, port=None, - auto_prompt_reset=True, ssh_key=None, quiet=True, - sync_multiplier=1, check_local_ip=True, - password_regex=r'(?i)(?:password:)|(?:passphrase for key)', - ssh_tunnels={}, spawn_local_ssh=True, - sync_original_prompt=True, ssh_config=None): - '''This logs the user into the given server. - - It uses - 'original_prompt' to try to find the prompt right after login. When it - finds the prompt it immediately tries to reset the prompt to something - more easily matched. The default 'original_prompt' is very optimistic - and is easily fooled. It's more reliable to try to match the original - prompt as exactly as possible to prevent false matches by server - strings such as the "Message Of The Day". On many systems you can - disable the MOTD on the remote server by creating a zero-length file - called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found - then this will not necessarily cause the login to fail. In the case of - a timeout when looking for the prompt we assume that the original - prompt was so weird that we could not match it, so we use a few tricks - to guess when we have reached the prompt. Then we hope for the best and - blindly try to reset the prompt to something more unique. If that fails - then login() raises an :class:`ExceptionPxssh` exception. - - In some situations it is not possible or desirable to reset the - original prompt. In this case, pass ``auto_prompt_reset=False`` to - inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh - uses a unique prompt in the :meth:`prompt` method. If the original prompt is - not reset then this will disable the :meth:`prompt` method unless you - manually set the :attr:`PROMPT` attribute. - - Set ``password_regex`` if there is a MOTD message with `password` in it. - Changing this is like playing in traffic, don't (p)expect it to match straight - away. - - If you require to connect to another SSH server from the your original SSH - connection set ``spawn_local_ssh`` to `False` and this will use your current - session to do so. Setting this option to `False` and not having an active session - will trigger an error. - - Set ``ssh_key`` to a file path to an SSH private key to use that SSH key - for the session authentication. - Set ``ssh_key`` to `True` to force passing the current SSH authentication socket - to the desired ``hostname``. - - Set ``ssh_config`` to a file path string of an SSH client config file to pass that - file to the client to handle itself. You may set any options you wish in here, however - doing so will require you to post extra information that you may not want to if you - run into issues. - ''' - - session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT] - session_init_regex_array = [] - session_init_regex_array.extend(session_regex_array) - session_init_regex_array.extend(["(?i)connection closed by remote host", EOF]) - - ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()]) - if quiet: - ssh_options = ssh_options + ' -q' - if not check_local_ip: - ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'" - if self.force_password: - ssh_options = ssh_options + ' ' + self.SSH_OPTS - if ssh_config is not None: - if spawn_local_ssh and not os.path.isfile(ssh_config): - raise ExceptionPxssh('SSH config does not exist or is not a file.') - ssh_options = ssh_options + '-F ' + ssh_config - if port is not None: - ssh_options = ssh_options + ' -p %s'%(str(port)) - if ssh_key is not None: - # Allow forwarding our SSH key to the current session - if ssh_key==True: - ssh_options = ssh_options + ' -A' - else: - if spawn_local_ssh and not os.path.isfile(ssh_key): - raise ExceptionPxssh('private ssh key does not exist or is not a file.') - ssh_options = ssh_options + ' -i %s' % (ssh_key) - - # SSH tunnels, make sure you know what you're putting into the lists - # under each heading. Do not expect these to open 100% of the time, - # The port you're requesting might be bound. - # - # The structure should be like this: - # { 'local': ['2424:localhost:22'], # Local SSH tunnels - # 'remote': ['2525:localhost:22'], # Remote SSH tunnels - # 'dynamic': [8888] } # Dynamic/SOCKS tunnels - if ssh_tunnels!={} and isinstance({},type(ssh_tunnels)): - tunnel_types = { - 'local':'L', - 'remote':'R', - 'dynamic':'D' - } - for tunnel_type in tunnel_types: - cmd_type = tunnel_types[tunnel_type] - if tunnel_type in ssh_tunnels: - tunnels = ssh_tunnels[tunnel_type] - for tunnel in tunnels: - if spawn_local_ssh==False: - tunnel = quote(str(tunnel)) - ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel) - cmd = "ssh %s -l %s %s" % (ssh_options, username, server) - if self.debug_command_string: - return(cmd) - - # Are we asking for a local ssh command or to spawn one in another session? - if spawn_local_ssh: - spawn._spawn(self, cmd) - else: - self.sendline(cmd) - - # This does not distinguish between a remote server 'password' prompt - # and a local ssh 'passphrase' prompt (for unlocking a private key). - i = self.expect(session_init_regex_array, timeout=login_timeout) - - # First phase - if i==0: - # New certificate -- always accept it. - # This is what you get if SSH does not have the remote host's - # public key stored in the 'known_hosts' cache. - self.sendline("yes") - i = self.expect(session_regex_array) - if i==2: # password or passphrase - self.sendline(password) - i = self.expect(session_regex_array) - if i==4: - self.sendline(terminal_type) - i = self.expect(session_regex_array) - if i==7: - self.close() - raise ExceptionPxssh('Could not establish connection to host') - - # Second phase - if i==0: - # This is weird. This should not happen twice in a row. - self.close() - raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.') - elif i==1: # can occur if you have a public key pair set to authenticate. - ### TODO: May NOT be OK if expect() got tricked and matched a false prompt. - pass - elif i==2: # password prompt again - # For incorrect passwords, some ssh servers will - # ask for the password again, others return 'denied' right away. - # If we get the password prompt again then this means - # we didn't get the password right the first time. - self.close() - raise ExceptionPxssh('password refused') - elif i==3: # permission denied -- password was bad. - self.close() - raise ExceptionPxssh('permission denied') - elif i==4: # terminal type again? WTF? - self.close() - raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.') - elif i==5: # Timeout - #This is tricky... I presume that we are at the command-line prompt. - #It may be that the shell prompt was so weird that we couldn't match - #it. Or it may be that we couldn't log in for some other reason. I - #can't be sure, but it's safe to guess that we did login because if - #I presume wrong and we are not logged in then this should be caught - #later when I try to set the shell prompt. - pass - elif i==6: # Connection closed by remote host - self.close() - raise ExceptionPxssh('connection closed') - else: # Unexpected - self.close() - raise ExceptionPxssh('unexpected login response') - if sync_original_prompt: - if not self.sync_original_prompt(sync_multiplier): - self.close() - raise ExceptionPxssh('could not synchronize with original prompt') - # We appear to be in. - # set shell prompt to something unique. - if auto_prompt_reset: - if not self.set_unique_prompt(): - self.close() - raise ExceptionPxssh('could not set shell prompt ' - '(received: %r, expected: %r).' % ( - self.before, self.PROMPT,)) - return True - - def logout (self): - '''Sends exit to the remote shell. - - If there are stopped jobs then this automatically sends exit twice. - ''' - self.sendline("exit") - index = self.expect([EOF, "(?i)there are stopped jobs"]) - if index==1: - self.sendline("exit") - self.expect(EOF) - self.close() - - def prompt(self, timeout=-1): - '''Match the next shell prompt. - - This is little more than a short-cut to the :meth:`~pexpect.spawn.expect` - method. Note that if you called :meth:`login` with - ``auto_prompt_reset=False``, then before calling :meth:`prompt` you must - set the :attr:`PROMPT` attribute to a regex that it will use for - matching the prompt. - - Calling :meth:`prompt` will erase the contents of the :attr:`before` - attribute even if no prompt is ever matched. If timeout is not given or - it is set to -1 then self.timeout is used. - - :return: True if the shell prompt was matched, False if the timeout was - reached. - ''' - - if timeout == -1: - timeout = self.timeout - i = self.expect([self.PROMPT, TIMEOUT], timeout=timeout) - if i==1: - return False - return True - - def set_unique_prompt(self): - '''This sets the remote prompt to something more unique than ``#`` or ``$``. - This makes it easier for the :meth:`prompt` method to match the shell prompt - unambiguously. This method is called automatically by the :meth:`login` - method, but you may want to call it manually if you somehow reset the - shell prompt. For example, if you 'su' to a different user then you - will need to manually reset the prompt. This sends shell commands to - the remote host to set the prompt, so this assumes the remote host is - ready to receive commands. - - Alternatively, you may use your own prompt pattern. In this case you - should call :meth:`login` with ``auto_prompt_reset=False``; then set the - :attr:`PROMPT` attribute to a regular expression. After that, the - :meth:`prompt` method will try to match your prompt pattern. - ''' - - self.sendline("unset PROMPT_COMMAND") - self.sendline(self.PROMPT_SET_SH) # sh-style - i = self.expect ([TIMEOUT, self.PROMPT], timeout=10) - if i == 0: # csh-style - self.sendline(self.PROMPT_SET_CSH) - i = self.expect([TIMEOUT, self.PROMPT], timeout=10) - if i == 0: - return False - return True - -# vi:ts=4:sw=4:expandtab:ft=python: diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py deleted file mode 100644 index ed0e657d739c..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/replwrap.py +++ /dev/null @@ -1,122 +0,0 @@ -"""Generic wrapper for read-eval-print-loops, a.k.a. interactive shells -""" -import os.path -import signal -import sys - -import pexpect - -PY3 = (sys.version_info[0] >= 3) - -if PY3: - basestring = str - -PEXPECT_PROMPT = u'[PEXPECT_PROMPT>' -PEXPECT_CONTINUATION_PROMPT = u'[PEXPECT_PROMPT+' - -class REPLWrapper(object): - """Wrapper for a REPL. - - :param cmd_or_spawn: This can either be an instance of :class:`pexpect.spawn` - in which a REPL has already been started, or a str command to start a new - REPL process. - :param str orig_prompt: The prompt to expect at first. - :param str prompt_change: A command to change the prompt to something more - unique. If this is ``None``, the prompt will not be changed. This will - be formatted with the new and continuation prompts as positional - parameters, so you can use ``{}`` style formatting to insert them into - the command. - :param str new_prompt: The more unique prompt to expect after the change. - :param str extra_init_cmd: Commands to do extra initialisation, such as - disabling pagers. - """ - def __init__(self, cmd_or_spawn, orig_prompt, prompt_change, - new_prompt=PEXPECT_PROMPT, - continuation_prompt=PEXPECT_CONTINUATION_PROMPT, - extra_init_cmd=None): - if isinstance(cmd_or_spawn, basestring): - self.child = pexpect.spawn(cmd_or_spawn, echo=False, encoding='utf-8') - else: - self.child = cmd_or_spawn - if self.child.echo: - # Existing spawn instance has echo enabled, disable it - # to prevent our input from being repeated to output. - self.child.setecho(False) - self.child.waitnoecho() - - if prompt_change is None: - self.prompt = orig_prompt - else: - self.set_prompt(orig_prompt, - prompt_change.format(new_prompt, continuation_prompt)) - self.prompt = new_prompt - self.continuation_prompt = continuation_prompt - - self._expect_prompt() - - if extra_init_cmd is not None: - self.run_command(extra_init_cmd) - - def set_prompt(self, orig_prompt, prompt_change): - self.child.expect(orig_prompt) - self.child.sendline(prompt_change) - - def _expect_prompt(self, timeout=-1): - return self.child.expect_exact([self.prompt, self.continuation_prompt], - timeout=timeout) - - def run_command(self, command, timeout=-1): - """Send a command to the REPL, wait for and return output. - - :param str command: The command to send. Trailing newlines are not needed. - This should be a complete block of input that will trigger execution; - if a continuation prompt is found after sending input, :exc:`ValueError` - will be raised. - :param int timeout: How long to wait for the next prompt. -1 means the - default from the :class:`pexpect.spawn` object (default 30 seconds). - None means to wait indefinitely. - """ - # Split up multiline commands and feed them in bit-by-bit - cmdlines = command.splitlines() - # splitlines ignores trailing newlines - add it back in manually - if command.endswith('\n'): - cmdlines.append('') - if not cmdlines: - raise ValueError("No command was given") - - res = [] - self.child.sendline(cmdlines[0]) - for line in cmdlines[1:]: - self._expect_prompt(timeout=timeout) - res.append(self.child.before) - self.child.sendline(line) - - # Command was fully submitted, now wait for the next prompt - if self._expect_prompt(timeout=timeout) == 1: - # We got the continuation prompt - command was incomplete - self.child.kill(signal.SIGINT) - self._expect_prompt(timeout=1) - raise ValueError("Continuation prompt found - input was incomplete:\n" - + command) - return u''.join(res + [self.child.before]) - -def python(command="python"): - """Start a Python shell and return a :class:`REPLWrapper` object.""" - return REPLWrapper(command, u">>> ", u"import sys; sys.ps1={0!r}; sys.ps2={1!r}") - -def bash(command="bash"): - """Start a bash shell and return a :class:`REPLWrapper` object.""" - bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh') - child = pexpect.spawn(command, ['--rcfile', bashrc], echo=False, - encoding='utf-8') - - # If the user runs 'env', the value of PS1 will be in the output. To avoid - # replwrap seeing that as the next prompt, we'll embed the marker characters - # for invisible characters in the prompt; these show up when inspecting the - # environment variable, but not when bash displays the prompt. - ps1 = PEXPECT_PROMPT[:5] + u'\\[\\]' + PEXPECT_PROMPT[5:] - ps2 = PEXPECT_CONTINUATION_PROMPT[:5] + u'\\[\\]' + PEXPECT_CONTINUATION_PROMPT[5:] - prompt_change = u"PS1='{0}' PS2='{1}' PROMPT_COMMAND=''".format(ps1, ps2) - - return REPLWrapper(child, u'\\$', prompt_change, - extra_init_cmd="export PAGER=cat") diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py deleted file mode 100644 index d9dfe76ba585..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/run.py +++ /dev/null @@ -1,157 +0,0 @@ -import sys -import types - -from .exceptions import EOF, TIMEOUT -from .pty_spawn import spawn - -def run(command, timeout=30, withexitstatus=False, events=None, - extra_args=None, logfile=None, cwd=None, env=None, **kwargs): - - ''' - This function runs the given command; waits for it to finish; then - returns all output as a string. STDERR is included in output. If the full - path to the command is not given then the path is searched. - - Note that lines are terminated by CR/LF (\\r\\n) combination even on - UNIX-like systems because this is the standard for pseudottys. If you set - 'withexitstatus' to true, then run will return a tuple of (command_output, - exitstatus). If 'withexitstatus' is false then this returns just - command_output. - - The run() function can often be used instead of creating a spawn instance. - For example, the following code uses spawn:: - - from pexpect import * - child = spawn('scp foo user@example.com:.') - child.expect('(?i)password') - child.sendline(mypassword) - - The previous code can be replace with the following:: - - from pexpect import * - run('scp foo user@example.com:.', events={'(?i)password': mypassword}) - - **Examples** - - Start the apache daemon on the local machine:: - - from pexpect import * - run("/usr/local/apache/bin/apachectl start") - - Check in a file using SVN:: - - from pexpect import * - run("svn ci -m 'automatic commit' my_file.py") - - Run a command and capture exit status:: - - from pexpect import * - (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1) - - The following will run SSH and execute 'ls -l' on the remote machine. The - password 'secret' will be sent if the '(?i)password' pattern is ever seen:: - - run("ssh username@machine.example.com 'ls -l'", - events={'(?i)password':'secret\\n'}) - - This will start mencoder to rip a video from DVD. This will also display - progress ticks every 5 seconds as it runs. For example:: - - from pexpect import * - def print_ticks(d): - print d['event_count'], - run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", - events={TIMEOUT:print_ticks}, timeout=5) - - The 'events' argument should be either a dictionary or a tuple list that - contains patterns and responses. Whenever one of the patterns is seen - in the command output, run() will send the associated response string. - So, run() in the above example can be also written as: - - run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", - events=[(TIMEOUT,print_ticks)], timeout=5) - - Use a tuple list for events if the command output requires a delicate - control over what pattern should be matched, since the tuple list is passed - to pexpect() as its pattern list, with the order of patterns preserved. - - Note that you should put newlines in your string if Enter is necessary. - - Like the example above, the responses may also contain a callback, either - a function or method. It should accept a dictionary value as an argument. - The dictionary contains all the locals from the run() function, so you can - access the child spawn object or any other variable defined in run() - (event_count, child, and extra_args are the most useful). A callback may - return True to stop the current run process. Otherwise run() continues - until the next event. A callback may also return a string which will be - sent to the child. 'extra_args' is not used by directly run(). It provides - a way to pass data to a callback function through run() through the locals - dictionary passed to a callback. - - Like :class:`spawn`, passing *encoding* will make it work with unicode - instead of bytes. You can pass *codec_errors* to control how errors in - encoding and decoding are handled. - ''' - if timeout == -1: - child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env, - **kwargs) - else: - child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, - cwd=cwd, env=env, **kwargs) - if isinstance(events, list): - patterns= [x for x,y in events] - responses = [y for x,y in events] - elif isinstance(events, dict): - patterns = list(events.keys()) - responses = list(events.values()) - else: - # This assumes EOF or TIMEOUT will eventually cause run to terminate. - patterns = None - responses = None - child_result_list = [] - event_count = 0 - while True: - try: - index = child.expect(patterns) - if isinstance(child.after, child.allowed_string_types): - child_result_list.append(child.before + child.after) - else: - # child.after may have been a TIMEOUT or EOF, - # which we don't want appended to the list. - child_result_list.append(child.before) - if isinstance(responses[index], child.allowed_string_types): - child.send(responses[index]) - elif (isinstance(responses[index], types.FunctionType) or - isinstance(responses[index], types.MethodType)): - callback_result = responses[index](locals()) - sys.stdout.flush() - if isinstance(callback_result, child.allowed_string_types): - child.send(callback_result) - elif callback_result: - break - else: - raise TypeError("parameter `event' at index {index} must be " - "a string, method, or function: {value!r}" - .format(index=index, value=responses[index])) - event_count = event_count + 1 - except TIMEOUT: - child_result_list.append(child.before) - break - except EOF: - child_result_list.append(child.before) - break - child_result = child.string_type().join(child_result_list) - if withexitstatus: - child.close() - return (child_result, child.exitstatus) - else: - return child_result - -def runu(command, timeout=30, withexitstatus=False, events=None, - extra_args=None, logfile=None, cwd=None, env=None, **kwargs): - """Deprecated: pass encoding to run() instead. - """ - kwargs.setdefault('encoding', 'utf-8') - return run(command, timeout=timeout, withexitstatus=withexitstatus, - events=events, extra_args=extra_args, logfile=logfile, cwd=cwd, - env=env, **kwargs) diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py deleted file mode 100644 index 5ab45b946795..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/screen.py +++ /dev/null @@ -1,431 +0,0 @@ -'''This implements a virtual screen. This is used to support ANSI terminal -emulation. The screen representation and state is implemented in this class. -Most of the methods are inspired by ANSI screen control codes. The -:class:`~pexpect.ANSI.ANSI` class extends this class to add parsing of ANSI -escape codes. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -import codecs -import copy -import sys - -import warnings - -warnings.warn(("pexpect.screen and pexpect.ANSI are deprecated. " - "We recommend using pyte to emulate a terminal screen: " - "https://pypi.python.org/pypi/pyte"), - stacklevel=2) - -NUL = 0 # Fill character; ignored on input. -ENQ = 5 # Transmit answerback message. -BEL = 7 # Ring the bell. -BS = 8 # Move cursor left. -HT = 9 # Move cursor to next tab stop. -LF = 10 # Line feed. -VT = 11 # Same as LF. -FF = 12 # Same as LF. -CR = 13 # Move cursor to left margin or newline. -SO = 14 # Invoke G1 character set. -SI = 15 # Invoke G0 character set. -XON = 17 # Resume transmission. -XOFF = 19 # Halt transmission. -CAN = 24 # Cancel escape sequence. -SUB = 26 # Same as CAN. -ESC = 27 # Introduce a control sequence. -DEL = 127 # Fill character; ignored on input. -SPACE = u' ' # Space or blank character. - -PY3 = (sys.version_info[0] >= 3) -if PY3: - unicode = str - -def constrain (n, min, max): - - '''This returns a number, n constrained to the min and max bounds. ''' - - if n < min: - return min - if n > max: - return max - return n - -class screen: - '''This object maintains the state of a virtual text screen as a - rectangular array. This maintains a virtual cursor position and handles - scrolling as characters are added. This supports most of the methods needed - by an ANSI text screen. Row and column indexes are 1-based (not zero-based, - like arrays). - - Characters are represented internally using unicode. Methods that accept - input characters, when passed 'bytes' (which in Python 2 is equivalent to - 'str'), convert them from the encoding specified in the 'encoding' - parameter to the constructor. Methods that return screen contents return - unicode strings, with the exception of __str__() under Python 2. Passing - ``encoding=None`` limits the API to only accept unicode input, so passing - bytes in will raise :exc:`TypeError`. - ''' - def __init__(self, r=24, c=80, encoding='latin-1', encoding_errors='replace'): - '''This initializes a blank screen of the given dimensions.''' - - self.rows = r - self.cols = c - self.encoding = encoding - self.encoding_errors = encoding_errors - if encoding is not None: - self.decoder = codecs.getincrementaldecoder(encoding)(encoding_errors) - else: - self.decoder = None - self.cur_r = 1 - self.cur_c = 1 - self.cur_saved_r = 1 - self.cur_saved_c = 1 - self.scroll_row_start = 1 - self.scroll_row_end = self.rows - self.w = [ [SPACE] * self.cols for _ in range(self.rows)] - - def _decode(self, s): - '''This converts from the external coding system (as passed to - the constructor) to the internal one (unicode). ''' - if self.decoder is not None: - return self.decoder.decode(s) - else: - raise TypeError("This screen was constructed with encoding=None, " - "so it does not handle bytes.") - - def _unicode(self): - '''This returns a printable representation of the screen as a unicode - string (which, under Python 3.x, is the same as 'str'). The end of each - screen line is terminated by a newline.''' - - return u'\n'.join ([ u''.join(c) for c in self.w ]) - - if PY3: - __str__ = _unicode - else: - __unicode__ = _unicode - - def __str__(self): - '''This returns a printable representation of the screen. The end of - each screen line is terminated by a newline. ''' - encoding = self.encoding or 'ascii' - return self._unicode().encode(encoding, 'replace') - - def dump (self): - '''This returns a copy of the screen as a unicode string. This is similar to - __str__/__unicode__ except that lines are not terminated with line - feeds.''' - - return u''.join ([ u''.join(c) for c in self.w ]) - - def pretty (self): - '''This returns a copy of the screen as a unicode string with an ASCII - text box around the screen border. This is similar to - __str__/__unicode__ except that it adds a box.''' - - top_bot = u'+' + u'-'*self.cols + u'+\n' - return top_bot + u'\n'.join([u'|'+line+u'|' for line in unicode(self).split(u'\n')]) + u'\n' + top_bot - - def fill (self, ch=SPACE): - - if isinstance(ch, bytes): - ch = self._decode(ch) - - self.fill_region (1,1,self.rows,self.cols, ch) - - def fill_region (self, rs,cs, re,ce, ch=SPACE): - - if isinstance(ch, bytes): - ch = self._decode(ch) - - rs = constrain (rs, 1, self.rows) - re = constrain (re, 1, self.rows) - cs = constrain (cs, 1, self.cols) - ce = constrain (ce, 1, self.cols) - if rs > re: - rs, re = re, rs - if cs > ce: - cs, ce = ce, cs - for r in range (rs, re+1): - for c in range (cs, ce + 1): - self.put_abs (r,c,ch) - - def cr (self): - '''This moves the cursor to the beginning (col 1) of the current row. - ''' - - self.cursor_home (self.cur_r, 1) - - def lf (self): - '''This moves the cursor down with scrolling. - ''' - - old_r = self.cur_r - self.cursor_down() - if old_r == self.cur_r: - self.scroll_up () - self.erase_line() - - def crlf (self): - '''This advances the cursor with CRLF properties. - The cursor will line wrap and the screen may scroll. - ''' - - self.cr () - self.lf () - - def newline (self): - '''This is an alias for crlf(). - ''' - - self.crlf() - - def put_abs (self, r, c, ch): - '''Screen array starts at 1 index.''' - - r = constrain (r, 1, self.rows) - c = constrain (c, 1, self.cols) - if isinstance(ch, bytes): - ch = self._decode(ch)[0] - else: - ch = ch[0] - self.w[r-1][c-1] = ch - - def put (self, ch): - '''This puts a characters at the current cursor position. - ''' - - if isinstance(ch, bytes): - ch = self._decode(ch) - - self.put_abs (self.cur_r, self.cur_c, ch) - - def insert_abs (self, r, c, ch): - '''This inserts a character at (r,c). Everything under - and to the right is shifted right one character. - The last character of the line is lost. - ''' - - if isinstance(ch, bytes): - ch = self._decode(ch) - - r = constrain (r, 1, self.rows) - c = constrain (c, 1, self.cols) - for ci in range (self.cols, c, -1): - self.put_abs (r,ci, self.get_abs(r,ci-1)) - self.put_abs (r,c,ch) - - def insert (self, ch): - - if isinstance(ch, bytes): - ch = self._decode(ch) - - self.insert_abs (self.cur_r, self.cur_c, ch) - - def get_abs (self, r, c): - - r = constrain (r, 1, self.rows) - c = constrain (c, 1, self.cols) - return self.w[r-1][c-1] - - def get (self): - - self.get_abs (self.cur_r, self.cur_c) - - def get_region (self, rs,cs, re,ce): - '''This returns a list of lines representing the region. - ''' - - rs = constrain (rs, 1, self.rows) - re = constrain (re, 1, self.rows) - cs = constrain (cs, 1, self.cols) - ce = constrain (ce, 1, self.cols) - if rs > re: - rs, re = re, rs - if cs > ce: - cs, ce = ce, cs - sc = [] - for r in range (rs, re+1): - line = u'' - for c in range (cs, ce + 1): - ch = self.get_abs (r,c) - line = line + ch - sc.append (line) - return sc - - def cursor_constrain (self): - '''This keeps the cursor within the screen area. - ''' - - self.cur_r = constrain (self.cur_r, 1, self.rows) - self.cur_c = constrain (self.cur_c, 1, self.cols) - - def cursor_home (self, r=1, c=1): # [{ROW};{COLUMN}H - - self.cur_r = r - self.cur_c = c - self.cursor_constrain () - - def cursor_back (self,count=1): # [{COUNT}D (not confused with down) - - self.cur_c = self.cur_c - count - self.cursor_constrain () - - def cursor_down (self,count=1): # [{COUNT}B (not confused with back) - - self.cur_r = self.cur_r + count - self.cursor_constrain () - - def cursor_forward (self,count=1): # [{COUNT}C - - self.cur_c = self.cur_c + count - self.cursor_constrain () - - def cursor_up (self,count=1): # [{COUNT}A - - self.cur_r = self.cur_r - count - self.cursor_constrain () - - def cursor_up_reverse (self): # M (called RI -- Reverse Index) - - old_r = self.cur_r - self.cursor_up() - if old_r == self.cur_r: - self.scroll_up() - - def cursor_force_position (self, r, c): # [{ROW};{COLUMN}f - '''Identical to Cursor Home.''' - - self.cursor_home (r, c) - - def cursor_save (self): # [s - '''Save current cursor position.''' - - self.cursor_save_attrs() - - def cursor_unsave (self): # [u - '''Restores cursor position after a Save Cursor.''' - - self.cursor_restore_attrs() - - def cursor_save_attrs (self): # 7 - '''Save current cursor position.''' - - self.cur_saved_r = self.cur_r - self.cur_saved_c = self.cur_c - - def cursor_restore_attrs (self): # 8 - '''Restores cursor position after a Save Cursor.''' - - self.cursor_home (self.cur_saved_r, self.cur_saved_c) - - def scroll_constrain (self): - '''This keeps the scroll region within the screen region.''' - - if self.scroll_row_start <= 0: - self.scroll_row_start = 1 - if self.scroll_row_end > self.rows: - self.scroll_row_end = self.rows - - def scroll_screen (self): # [r - '''Enable scrolling for entire display.''' - - self.scroll_row_start = 1 - self.scroll_row_end = self.rows - - def scroll_screen_rows (self, rs, re): # [{start};{end}r - '''Enable scrolling from row {start} to row {end}.''' - - self.scroll_row_start = rs - self.scroll_row_end = re - self.scroll_constrain() - - def scroll_down (self): # D - '''Scroll display down one line.''' - - # Screen is indexed from 1, but arrays are indexed from 0. - s = self.scroll_row_start - 1 - e = self.scroll_row_end - 1 - self.w[s+1:e+1] = copy.deepcopy(self.w[s:e]) - - def scroll_up (self): # M - '''Scroll display up one line.''' - - # Screen is indexed from 1, but arrays are indexed from 0. - s = self.scroll_row_start - 1 - e = self.scroll_row_end - 1 - self.w[s:e] = copy.deepcopy(self.w[s+1:e+1]) - - def erase_end_of_line (self): # [0K -or- [K - '''Erases from the current cursor position to the end of the current - line.''' - - self.fill_region (self.cur_r, self.cur_c, self.cur_r, self.cols) - - def erase_start_of_line (self): # [1K - '''Erases from the current cursor position to the start of the current - line.''' - - self.fill_region (self.cur_r, 1, self.cur_r, self.cur_c) - - def erase_line (self): # [2K - '''Erases the entire current line.''' - - self.fill_region (self.cur_r, 1, self.cur_r, self.cols) - - def erase_down (self): # [0J -or- [J - '''Erases the screen from the current line down to the bottom of the - screen.''' - - self.erase_end_of_line () - self.fill_region (self.cur_r + 1, 1, self.rows, self.cols) - - def erase_up (self): # [1J - '''Erases the screen from the current line up to the top of the - screen.''' - - self.erase_start_of_line () - self.fill_region (self.cur_r-1, 1, 1, self.cols) - - def erase_screen (self): # [2J - '''Erases the screen with the background color.''' - - self.fill () - - def set_tab (self): # H - '''Sets a tab at the current position.''' - - pass - - def clear_tab (self): # [g - '''Clears tab at the current position.''' - - pass - - def clear_all_tabs (self): # [3g - '''Clears all tabs.''' - - pass - -# Insert line Esc [ Pn L -# Delete line Esc [ Pn M -# Delete character Esc [ Pn P -# Scrolling region Esc [ Pn(top);Pn(bot) r - diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py deleted file mode 100644 index 589d5ec92465..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py +++ /dev/null @@ -1,522 +0,0 @@ -from io import StringIO, BytesIO -import codecs -import os -import sys -import re -import errno -from .exceptions import ExceptionPexpect, EOF, TIMEOUT -from .expect import Expecter, searcher_string, searcher_re - -PY3 = (sys.version_info[0] >= 3) -text_type = str if PY3 else unicode - -class _NullCoder(object): - """Pass bytes through unchanged.""" - @staticmethod - def encode(b, final=False): - return b - - @staticmethod - def decode(b, final=False): - return b - -class SpawnBase(object): - """A base class providing the backwards-compatible spawn API for Pexpect. - - This should not be instantiated directly: use :class:`pexpect.spawn` or - :class:`pexpect.fdpexpect.fdspawn`. - """ - encoding = None - pid = None - flag_eof = False - - def __init__(self, timeout=60, maxread=2000, searchwindowsize=None, - logfile=None, encoding=None, codec_errors='strict'): - self.stdin = sys.stdin - self.stdout = sys.stdout - self.stderr = sys.stderr - - self.searcher = None - self.ignorecase = False - self.before = None - self.after = None - self.match = None - self.match_index = None - self.terminated = True - self.exitstatus = None - self.signalstatus = None - # status returned by os.waitpid - self.status = None - # the child file descriptor is initially closed - self.child_fd = -1 - self.timeout = timeout - self.delimiter = EOF - self.logfile = logfile - # input from child (read_nonblocking) - self.logfile_read = None - # output to send (send, sendline) - self.logfile_send = None - # max bytes to read at one time into buffer - self.maxread = maxread - # Data before searchwindowsize point is preserved, but not searched. - self.searchwindowsize = searchwindowsize - # Delay used before sending data to child. Time in seconds. - # Set this to None to skip the time.sleep() call completely. - self.delaybeforesend = 0.05 - # Used by close() to give kernel time to update process status. - # Time in seconds. - self.delayafterclose = 0.1 - # Used by terminate() to give kernel time to update process status. - # Time in seconds. - self.delayafterterminate = 0.1 - # Delay in seconds to sleep after each call to read_nonblocking(). - # Set this to None to skip the time.sleep() call completely: that - # would restore the behavior from pexpect-2.0 (for performance - # reasons or because you don't want to release Python's global - # interpreter lock). - self.delayafterread = 0.0001 - self.softspace = False - self.name = '<' + repr(self) + '>' - self.closed = True - - # Unicode interface - self.encoding = encoding - self.codec_errors = codec_errors - if encoding is None: - # bytes mode (accepts some unicode for backwards compatibility) - self._encoder = self._decoder = _NullCoder() - self.string_type = bytes - self.buffer_type = BytesIO - self.crlf = b'\r\n' - if PY3: - self.allowed_string_types = (bytes, str) - self.linesep = os.linesep.encode('ascii') - def write_to_stdout(b): - try: - return sys.stdout.buffer.write(b) - except AttributeError: - # If stdout has been replaced, it may not have .buffer - return sys.stdout.write(b.decode('ascii', 'replace')) - self.write_to_stdout = write_to_stdout - else: - self.allowed_string_types = (basestring,) # analysis:ignore - self.linesep = os.linesep - self.write_to_stdout = sys.stdout.write - else: - # unicode mode - self._encoder = codecs.getincrementalencoder(encoding)(codec_errors) - self._decoder = codecs.getincrementaldecoder(encoding)(codec_errors) - self.string_type = text_type - self.buffer_type = StringIO - self.crlf = u'\r\n' - self.allowed_string_types = (text_type, ) - if PY3: - self.linesep = os.linesep - else: - self.linesep = os.linesep.decode('ascii') - # This can handle unicode in both Python 2 and 3 - self.write_to_stdout = sys.stdout.write - # storage for async transport - self.async_pw_transport = None - # This is the read buffer. See maxread. - self._buffer = self.buffer_type() - - def _log(self, s, direction): - if self.logfile is not None: - self.logfile.write(s) - self.logfile.flush() - second_log = self.logfile_send if (direction=='send') else self.logfile_read - if second_log is not None: - second_log.write(s) - second_log.flush() - - # For backwards compatibility, in bytes mode (when encoding is None) - # unicode is accepted for send and expect. Unicode mode is strictly unicode - # only. - def _coerce_expect_string(self, s): - if self.encoding is None and not isinstance(s, bytes): - return s.encode('ascii') - return s - - def _coerce_send_string(self, s): - if self.encoding is None and not isinstance(s, bytes): - return s.encode('utf-8') - return s - - def _get_buffer(self): - return self._buffer.getvalue() - - def _set_buffer(self, value): - self._buffer = self.buffer_type() - self._buffer.write(value) - - # This property is provided for backwards compatibility (self.buffer used - # to be a string/bytes object) - buffer = property(_get_buffer, _set_buffer) - - def read_nonblocking(self, size=1, timeout=None): - """This reads data from the file descriptor. - - This is a simple implementation suitable for a regular file. Subclasses using ptys or pipes should override it. - - The timeout parameter is ignored. - """ - - try: - s = os.read(self.child_fd, size) - except OSError as err: - if err.args[0] == errno.EIO: - # Linux-style EOF - self.flag_eof = True - raise EOF('End Of File (EOF). Exception style platform.') - raise - if s == b'': - # BSD-style EOF - self.flag_eof = True - raise EOF('End Of File (EOF). Empty string style platform.') - - s = self._decoder.decode(s, final=False) - self._log(s, 'read') - return s - - def _pattern_type_err(self, pattern): - raise TypeError('got {badtype} ({badobj!r}) as pattern, must be one' - ' of: {goodtypes}, pexpect.EOF, pexpect.TIMEOUT'\ - .format(badtype=type(pattern), - badobj=pattern, - goodtypes=', '.join([str(ast)\ - for ast in self.allowed_string_types]) - ) - ) - - def compile_pattern_list(self, patterns): - '''This compiles a pattern-string or a list of pattern-strings. - Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of - those. Patterns may also be None which results in an empty list (you - might do this if waiting for an EOF or TIMEOUT condition without - expecting any pattern). - - This is used by expect() when calling expect_list(). Thus expect() is - nothing more than:: - - cpl = self.compile_pattern_list(pl) - return self.expect_list(cpl, timeout) - - If you are using expect() within a loop it may be more - efficient to compile the patterns first and then call expect_list(). - This avoid calls in a loop to compile_pattern_list():: - - cpl = self.compile_pattern_list(my_pattern) - while some_condition: - ... - i = self.expect_list(cpl, timeout) - ... - ''' - - if patterns is None: - return [] - if not isinstance(patterns, list): - patterns = [patterns] - - # Allow dot to match \n - compile_flags = re.DOTALL - if self.ignorecase: - compile_flags = compile_flags | re.IGNORECASE - compiled_pattern_list = [] - for idx, p in enumerate(patterns): - if isinstance(p, self.allowed_string_types): - p = self._coerce_expect_string(p) - compiled_pattern_list.append(re.compile(p, compile_flags)) - elif p is EOF: - compiled_pattern_list.append(EOF) - elif p is TIMEOUT: - compiled_pattern_list.append(TIMEOUT) - elif isinstance(p, type(re.compile(''))): - compiled_pattern_list.append(p) - else: - self._pattern_type_err(p) - return compiled_pattern_list - - def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw): - '''This seeks through the stream until a pattern is matched. The - pattern is overloaded and may take several types. The pattern can be a - StringType, EOF, a compiled re, or a list of any of those types. - Strings will be compiled to re types. This returns the index into the - pattern list. If the pattern was not a list this returns index 0 on a - successful match. This may raise exceptions for EOF or TIMEOUT. To - avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern - list. That will cause expect to match an EOF or TIMEOUT condition - instead of raising an exception. - - If you pass a list of patterns and more than one matches, the first - match in the stream is chosen. If more than one pattern matches at that - point, the leftmost in the pattern list is chosen. For example:: - - # the input is 'foobar' - index = p.expect(['bar', 'foo', 'foobar']) - # returns 1('foo') even though 'foobar' is a "better" match - - Please note, however, that buffering can affect this behavior, since - input arrives in unpredictable chunks. For example:: - - # the input is 'foobar' - index = p.expect(['foobar', 'foo']) - # returns 0('foobar') if all input is available at once, - # but returns 1('foo') if parts of the final 'bar' arrive late - - When a match is found for the given pattern, the class instance - attribute *match* becomes an re.MatchObject result. Should an EOF - or TIMEOUT pattern match, then the match attribute will be an instance - of that exception class. The pairing before and after class - instance attributes are views of the data preceding and following - the matching pattern. On general exception, class attribute - *before* is all data received up to the exception, while *match* and - *after* attributes are value None. - - When the keyword argument timeout is -1 (default), then TIMEOUT will - raise after the default value specified by the class timeout - attribute. When None, TIMEOUT will not be raised and may block - indefinitely until match. - - When the keyword argument searchwindowsize is -1 (default), then the - value specified by the class maxread attribute is used. - - A list entry may be EOF or TIMEOUT instead of a string. This will - catch these exceptions and return the index of the list entry instead - of raising the exception. The attribute 'after' will be set to the - exception type. The attribute 'match' will be None. This allows you to - write code like this:: - - index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT]) - if index == 0: - do_something() - elif index == 1: - do_something_else() - elif index == 2: - do_some_other_thing() - elif index == 3: - do_something_completely_different() - - instead of code like this:: - - try: - index = p.expect(['good', 'bad']) - if index == 0: - do_something() - elif index == 1: - do_something_else() - except EOF: - do_some_other_thing() - except TIMEOUT: - do_something_completely_different() - - These two forms are equivalent. It all depends on what you want. You - can also just expect the EOF if you are waiting for all output of a - child to finish. For example:: - - p = pexpect.spawn('/bin/ls') - p.expect(pexpect.EOF) - print p.before - - If you are trying to optimize for speed then see expect_list(). - - On Python 3.4, or Python 3.3 with asyncio installed, passing - ``async_=True`` will make this return an :mod:`asyncio` coroutine, - which you can yield from to get the same result that this method would - normally give directly. So, inside a coroutine, you can replace this code:: - - index = p.expect(patterns) - - With this non-blocking form:: - - index = yield from p.expect(patterns, async_=True) - ''' - if 'async' in kw: - async_ = kw.pop('async') - if kw: - raise TypeError("Unknown keyword arguments: {}".format(kw)) - - compiled_pattern_list = self.compile_pattern_list(pattern) - return self.expect_list(compiled_pattern_list, - timeout, searchwindowsize, async_) - - def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1, - async_=False, **kw): - '''This takes a list of compiled regular expressions and returns the - index into the pattern_list that matched the child output. The list may - also contain EOF or TIMEOUT(which are not compiled regular - expressions). This method is similar to the expect() method except that - expect_list() does not recompile the pattern list on every call. This - may help if you are trying to optimize for speed, otherwise just use - the expect() method. This is called by expect(). - - - Like :meth:`expect`, passing ``async_=True`` will make this return an - asyncio coroutine. - ''' - if timeout == -1: - timeout = self.timeout - if 'async' in kw: - async_ = kw.pop('async') - if kw: - raise TypeError("Unknown keyword arguments: {}".format(kw)) - - exp = Expecter(self, searcher_re(pattern_list), searchwindowsize) - if async_: - from ._async import expect_async - return expect_async(exp, timeout) - else: - return exp.expect_loop(timeout) - - def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1, - async_=False, **kw): - - '''This is similar to expect(), but uses plain string matching instead - of compiled regular expressions in 'pattern_list'. The 'pattern_list' - may be a string; a list or other sequence of strings; or TIMEOUT and - EOF. - - This call might be faster than expect() for two reasons: string - searching is faster than RE matching and it is possible to limit the - search to just the end of the input buffer. - - This method is also useful when you don't want to have to worry about - escaping regular expression characters that you want to match. - - Like :meth:`expect`, passing ``async_=True`` will make this return an - asyncio coroutine. - ''' - if timeout == -1: - timeout = self.timeout - if 'async' in kw: - async_ = kw.pop('async') - if kw: - raise TypeError("Unknown keyword arguments: {}".format(kw)) - - if (isinstance(pattern_list, self.allowed_string_types) or - pattern_list in (TIMEOUT, EOF)): - pattern_list = [pattern_list] - - def prepare_pattern(pattern): - if pattern in (TIMEOUT, EOF): - return pattern - if isinstance(pattern, self.allowed_string_types): - return self._coerce_expect_string(pattern) - self._pattern_type_err(pattern) - - try: - pattern_list = iter(pattern_list) - except TypeError: - self._pattern_type_err(pattern_list) - pattern_list = [prepare_pattern(p) for p in pattern_list] - - exp = Expecter(self, searcher_string(pattern_list), searchwindowsize) - if async_: - from ._async import expect_async - return expect_async(exp, timeout) - else: - return exp.expect_loop(timeout) - - def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): - '''This is the common loop used inside expect. The 'searcher' should be - an instance of searcher_re or searcher_string, which describes how and - what to search for in the input. - - See expect() for other arguments, return value and exceptions. ''' - - exp = Expecter(self, searcher, searchwindowsize) - return exp.expect_loop(timeout) - - def read(self, size=-1): - '''This reads at most "size" bytes from the file (less if the read hits - EOF before obtaining size bytes). If the size argument is negative or - omitted, read all data until EOF is reached. The bytes are returned as - a string object. An empty string is returned when EOF is encountered - immediately. ''' - - if size == 0: - return self.string_type() - if size < 0: - # delimiter default is EOF - self.expect(self.delimiter) - return self.before - - # I could have done this more directly by not using expect(), but - # I deliberately decided to couple read() to expect() so that - # I would catch any bugs early and ensure consistent behavior. - # It's a little less efficient, but there is less for me to - # worry about if I have to later modify read() or expect(). - # Note, it's OK if size==-1 in the regex. That just means it - # will never match anything in which case we stop only on EOF. - cre = re.compile(self._coerce_expect_string('.{%d}' % size), re.DOTALL) - # delimiter default is EOF - index = self.expect([cre, self.delimiter]) - if index == 0: - ### FIXME self.before should be ''. Should I assert this? - return self.after - return self.before - - def readline(self, size=-1): - '''This reads and returns one entire line. The newline at the end of - line is returned as part of the string, unless the file ends without a - newline. An empty string is returned if EOF is encountered immediately. - This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because - this is what the pseudotty device returns. So contrary to what you may - expect you will receive newlines as \\r\\n. - - If the size argument is 0 then an empty string is returned. In all - other cases the size argument is ignored, which is not standard - behavior for a file-like object. ''' - - if size == 0: - return self.string_type() - # delimiter default is EOF - index = self.expect([self.crlf, self.delimiter]) - if index == 0: - return self.before + self.crlf - else: - return self.before - - def __iter__(self): - '''This is to support iterators over a file-like object. - ''' - return iter(self.readline, self.string_type()) - - def readlines(self, sizehint=-1): - '''This reads until EOF using readline() and returns a list containing - the lines thus read. The optional 'sizehint' argument is ignored. - Remember, because this reads until EOF that means the child - process should have closed its stdout. If you run this method on - a child that is still running with its stdout open then this - method will block until it timesout.''' - - lines = [] - while True: - line = self.readline() - if not line: - break - lines.append(line) - return lines - - def fileno(self): - '''Expose file descriptor for a file-like interface - ''' - return self.child_fd - - def flush(self): - '''This does nothing. It is here to support the interface for a - File-like object. ''' - pass - - def isatty(self): - """Overridden in subclass using tty""" - return False - - # For 'with spawn(...) as child:' - def __enter__(self): - return self - - def __exit__(self, etype, evalue, tb): - # We rely on subclasses to implement close(). If they don't, it's not - # clear what a context manager should do. - self.close() diff --git a/lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py b/lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py deleted file mode 100644 index f77451960900..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/pexpect/utils.py +++ /dev/null @@ -1,187 +0,0 @@ -import os -import sys -import stat -import select -import time -import errno - -try: - InterruptedError -except NameError: - # Alias Python2 exception to Python3 - InterruptedError = select.error - -if sys.version_info[0] >= 3: - string_types = (str,) -else: - string_types = (unicode, str) - - -def is_executable_file(path): - """Checks that path is an executable regular file, or a symlink towards one. - - This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``. - """ - # follow symlinks, - fpath = os.path.realpath(path) - - if not os.path.isfile(fpath): - # non-files (directories, fifo, etc.) - return False - - mode = os.stat(fpath).st_mode - - if (sys.platform.startswith('sunos') - and os.getuid() == 0): - # When root on Solaris, os.X_OK is True for *all* files, irregardless - # of their executability -- instead, any permission bit of any user, - # group, or other is fine enough. - # - # (This may be true for other "Unix98" OS's such as HP-UX and AIX) - return bool(mode & (stat.S_IXUSR | - stat.S_IXGRP | - stat.S_IXOTH)) - - return os.access(fpath, os.X_OK) - - -def which(filename, env=None): - '''This takes a given filename; tries to find it in the environment path; - then checks if it is executable. This returns the full path to the filename - if found and executable. Otherwise this returns None.''' - - # Special case where filename contains an explicit path. - if os.path.dirname(filename) != '' and is_executable_file(filename): - return filename - if env is None: - env = os.environ - p = env.get('PATH') - if not p: - p = os.defpath - pathlist = p.split(os.pathsep) - for path in pathlist: - ff = os.path.join(path, filename) - if is_executable_file(ff): - return ff - return None - - -def split_command_line(command_line): - - '''This splits a command line into a list of arguments. It splits arguments - on spaces, but handles embedded quotes, doublequotes, and escaped - characters. It's impossible to do this with a regular expression, so I - wrote a little state machine to parse the command line. ''' - - arg_list = [] - arg = '' - - # Constants to name the states we can be in. - state_basic = 0 - state_esc = 1 - state_singlequote = 2 - state_doublequote = 3 - # The state when consuming whitespace between commands. - state_whitespace = 4 - state = state_basic - - for c in command_line: - if state == state_basic or state == state_whitespace: - if c == '\\': - # Escape the next character - state = state_esc - elif c == r"'": - # Handle single quote - state = state_singlequote - elif c == r'"': - # Handle double quote - state = state_doublequote - elif c.isspace(): - # Add arg to arg_list if we aren't in the middle of whitespace. - if state == state_whitespace: - # Do nothing. - None - else: - arg_list.append(arg) - arg = '' - state = state_whitespace - else: - arg = arg + c - state = state_basic - elif state == state_esc: - arg = arg + c - state = state_basic - elif state == state_singlequote: - if c == r"'": - state = state_basic - else: - arg = arg + c - elif state == state_doublequote: - if c == r'"': - state = state_basic - else: - arg = arg + c - - if arg != '': - arg_list.append(arg) - return arg_list - - -def select_ignore_interrupts(iwtd, owtd, ewtd, timeout=None): - - '''This is a wrapper around select.select() that ignores signals. If - select.select raises a select.error exception and errno is an EINTR - error then it is ignored. Mainly this is used to ignore sigwinch - (terminal resize). ''' - - # if select() is interrupted by a signal (errno==EINTR) then - # we loop back and enter the select() again. - if timeout is not None: - end_time = time.time() + timeout - while True: - try: - return select.select(iwtd, owtd, ewtd, timeout) - except InterruptedError: - err = sys.exc_info()[1] - if err.args[0] == errno.EINTR: - # if we loop back we have to subtract the - # amount of time we already waited. - if timeout is not None: - timeout = end_time - time.time() - if timeout < 0: - return([], [], []) - else: - # something else caused the select.error, so - # this actually is an exception. - raise - - -def poll_ignore_interrupts(fds, timeout=None): - '''Simple wrapper around poll to register file descriptors and - ignore signals.''' - - if timeout is not None: - end_time = time.time() + timeout - - poller = select.poll() - for fd in fds: - poller.register(fd, select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR) - - while True: - try: - timeout_ms = None if timeout is None else timeout * 1000 - results = poller.poll(timeout_ms) - return [afd for afd, _ in results] - except InterruptedError: - err = sys.exc_info()[1] - if err.args[0] == errno.EINTR: - # if we loop back we have to subtract the - # amount of time we already waited. - if timeout is not None: - timeout = end_time - time.time() - if timeout < 0: - return [] - else: - # something else caused the select.error, so - # this actually is an exception. - raise diff --git a/lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt b/lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt deleted file mode 100644 index 1894122c85c5..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/requirements-testing.txt +++ /dev/null @@ -1,5 +0,0 @@ -pytest -pytest-cov -coverage -coveralls -pytest-capturelog diff --git a/lldb/third_party/Python/module/pexpect-4.6/setup.cfg b/lldb/third_party/Python/module/pexpect-4.6/setup.cfg deleted file mode 100644 index b2a82dcdc6c5..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[tool:pytest] -norecursedirs = .git - -[bdist_wheel] -universal=1 diff --git a/lldb/third_party/Python/module/pexpect-4.6/setup.py b/lldb/third_party/Python/module/pexpect-4.6/setup.py deleted file mode 100644 index 4e61e795c2af..000000000000 --- a/lldb/third_party/Python/module/pexpect-4.6/setup.py +++ /dev/null @@ -1,71 +0,0 @@ -# encoding: utf-8 -from distutils.core import setup -import os -import re -import sys - -if any(a == 'bdist_wheel' for a in sys.argv): - from setuptools import setup - -with open(os.path.join(os.path.dirname(__file__), 'pexpect', '__init__.py'), 'r') as f: - for line in f: - version_match = re.search(r"__version__ = ['\"]([^'\"]*)['\"]", line) - if version_match: - version = version_match.group(1) - break - else: - raise Exception("couldn't find version number") - -long_description = """ -Pexpect is a pure Python module for spawning child applications; controlling -them; and responding to expected patterns in their output. Pexpect works like -Don Libes' Expect. Pexpect allows your script to spawn a child application and -control it as if a human were typing commands. - -Pexpect can be used for automating interactive applications such as ssh, ftp, -passwd, telnet, etc. It can be used to a automate setup scripts for duplicating -software package installations on different servers. It can be used for -automated software testing. Pexpect is in the spirit of Don Libes' Expect, but -Pexpect is pure Python. - -The main features of Pexpect require the pty module in the Python standard -library, which is only available on Unix-like systems. Some features—waiting -for patterns from file descriptors or subprocesses—are also available on -Windows. -""" - -setup(name='pexpect', - version=version, - packages=['pexpect'], - package_data={'pexpect': ['bashrc.sh']}, - description='Pexpect allows easy control of interactive console applications.', - long_description=long_description, - author='Noah Spurrier; Thomas Kluyver; Jeff Quast', - author_email='noah@noah.org, thomas@kluyver.me.uk, contact@jeffquast.com', - url='https://pexpect.readthedocs.io/', - license='ISC license', - platforms='UNIX', - classifiers = [ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: ISC License (ISCL)', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Topic :: Software Development', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Quality Assurance', - 'Topic :: Software Development :: Testing', - 'Topic :: System', - 'Topic :: System :: Archiving :: Packaging', - 'Topic :: System :: Installation/Setup', - 'Topic :: System :: Shells', - 'Topic :: System :: Software Distribution', - 'Topic :: Terminals', - ], - install_requires=['ptyprocess>=0.5'], -) diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/.gitignore b/lldb/third_party/Python/module/ptyprocess-0.6.0/.gitignore deleted file mode 100644 index 4b46c269a4c2..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -__pycache__ -*.pyc - -/build/ -/dist/ -MANIFEST -docs/_build/ diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/.travis.yml b/lldb/third_party/Python/module/ptyprocess-0.6.0/.travis.yml deleted file mode 100644 index 34b391808af3..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: python -python: - - "3.6" - - "3.5" - - "3.4" - - "2.7" -# command to run tests -script: py.test --verbose --verbose -sudo: False diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE b/lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE deleted file mode 100644 index 9c772742de96..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ -Ptyprocess is under the ISC license, as code derived from Pexpect. - http://opensource.org/licenses/ISC - -Copyright (c) 2013-2014, Pexpect development team -Copyright (c) 2012, Noah Spurrier - -PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY PURPOSE -WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE COPYRIGHT NOTICE -AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. THE SOFTWARE IS PROVIDED -"AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT -SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/README.rst b/lldb/third_party/Python/module/ptyprocess-0.6.0/README.rst deleted file mode 100644 index b928e8608d1a..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/README.rst +++ /dev/null @@ -1,15 +0,0 @@ -Launch a subprocess in a pseudo terminal (pty), and interact with both the -process and its pty. - -Sometimes, piping stdin and stdout is not enough. There might be a password -prompt that doesn't read from stdin, output that changes when it's going to a -pipe rather than a terminal, or curses-style interfaces that rely on a terminal. -If you need to automate these things, running the process in a pseudo terminal -(pty) is the answer. - -Interface:: - - p = PtyProcessUnicode.spawn(['python']) - p.read(20) - p.write('6+6\n') - p.read(20) diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py b/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py deleted file mode 100644 index e633d0cddacd..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Run a subprocess in a pseudo terminal""" -from .ptyprocess import PtyProcess, PtyProcessUnicode, PtyProcessError - -__version__ = '0.6.0' diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py b/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py deleted file mode 100644 index a8d05fe5a3d1..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Substitute for the forkpty system call, to support Solaris. -""" -import os -import errno - -from pty import (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD) -from .util import PtyProcessError - -def fork_pty(): - '''This implements a substitute for the forkpty system call. This - should be more portable than the pty.fork() function. Specifically, - this should work on Solaris. - - Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to - resolve the issue with Python's pty.fork() not supporting Solaris, - particularly ssh. Based on patch to posixmodule.c authored by Noah - Spurrier:: - - http://mail.python.org/pipermail/python-dev/2003-May/035281.html - - ''' - - parent_fd, child_fd = os.openpty() - if parent_fd < 0 or child_fd < 0: - raise OSError("os.openpty() failed") - - pid = os.fork() - if pid == CHILD: - # Child. - os.close(parent_fd) - pty_make_controlling_tty(child_fd) - - os.dup2(child_fd, STDIN_FILENO) - os.dup2(child_fd, STDOUT_FILENO) - os.dup2(child_fd, STDERR_FILENO) - - else: - # Parent. - os.close(child_fd) - - return pid, parent_fd - -def pty_make_controlling_tty(tty_fd): - '''This makes the pseudo-terminal the controlling tty. This should be - more portable than the pty.fork() function. Specifically, this should - work on Solaris. ''' - - child_name = os.ttyname(tty_fd) - - # Disconnect from controlling tty, if any. Raises OSError of ENXIO - # if there was no controlling tty to begin with, such as when - # executed by a cron(1) job. - try: - fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) - os.close(fd) - except OSError as err: - if err.errno != errno.ENXIO: - raise - - os.setsid() - - # Verify we are disconnected from controlling tty by attempting to open - # it again. We expect that OSError of ENXIO should always be raised. - try: - fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) - os.close(fd) - raise PtyProcessError("OSError of errno.ENXIO should be raised.") - except OSError as err: - if err.errno != errno.ENXIO: - raise - - # Verify we can open child pty. - fd = os.open(child_name, os.O_RDWR) - os.close(fd) - - # Verify we now have a controlling tty. - fd = os.open("/dev/tty", os.O_WRONLY) - os.close(fd) diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py b/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py deleted file mode 100644 index a58741e8335e..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py +++ /dev/null @@ -1,836 +0,0 @@ -import codecs -import errno -import fcntl -import io -import os -import pty -import resource -import signal -import struct -import sys -import termios -import time - -try: - import builtins # Python 3 -except ImportError: - import __builtin__ as builtins # Python 2 - -# Constants -from pty import (STDIN_FILENO, CHILD) - -from .util import which, PtyProcessError - -_platform = sys.platform.lower() - -# Solaris uses internal __fork_pty(). All others use pty.fork(). -_is_solaris = ( - _platform.startswith('solaris') or - _platform.startswith('sunos')) - -if _is_solaris: - use_native_pty_fork = False - from . import _fork_pty -else: - use_native_pty_fork = True - -PY3 = sys.version_info[0] >= 3 - -if PY3: - def _byte(i): - return bytes([i]) -else: - def _byte(i): - return chr(i) - - class FileNotFoundError(OSError): pass - class TimeoutError(OSError): pass - -_EOF, _INTR = None, None - -def _make_eof_intr(): - """Set constants _EOF and _INTR. - - This avoids doing potentially costly operations on module load. - """ - global _EOF, _INTR - if (_EOF is not None) and (_INTR is not None): - return - - # inherit EOF and INTR definitions from controlling process. - try: - from termios import VEOF, VINTR - fd = None - for name in 'stdin', 'stdout': - stream = getattr(sys, '__%s__' % name, None) - if stream is None or not hasattr(stream, 'fileno'): - continue - try: - fd = stream.fileno() - except ValueError: - continue - if fd is None: - # no fd, raise ValueError to fallback on CEOF, CINTR - raise ValueError("No stream has a fileno") - intr = ord(termios.tcgetattr(fd)[6][VINTR]) - eof = ord(termios.tcgetattr(fd)[6][VEOF]) - except (ImportError, OSError, IOError, ValueError, termios.error): - # unless the controlling process is also not a terminal, - # such as cron(1), or when stdin and stdout are both closed. - # Fall-back to using CEOF and CINTR. There - try: - from termios import CEOF, CINTR - (intr, eof) = (CINTR, CEOF) - except ImportError: - # ^C, ^D - (intr, eof) = (3, 4) - - _INTR = _byte(intr) - _EOF = _byte(eof) - -# setecho and setwinsize are pulled out here because on some platforms, we need -# to do this from the child before we exec() - -def _setecho(fd, state): - errmsg = 'setecho() may not be called on this platform (it may still be possible to enable/disable echo when spawning the child process)' - - try: - attr = termios.tcgetattr(fd) - except termios.error as err: - if err.args[0] == errno.EINVAL: - raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg)) - raise - - if state: - attr[3] = attr[3] | termios.ECHO - else: - attr[3] = attr[3] & ~termios.ECHO - - try: - # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent and - # blocked on some platforms. TCSADRAIN would probably be ideal. - termios.tcsetattr(fd, termios.TCSANOW, attr) - except IOError as err: - if err.args[0] == errno.EINVAL: - raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg)) - raise - -def _setwinsize(fd, rows, cols): - # Some very old platforms have a bug that causes the value for - # termios.TIOCSWINSZ to be truncated. There was a hack here to work - # around this, but it caused problems with newer platforms so has been - # removed. For details see https://github.com/pexpect/pexpect/issues/39 - TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561) - # Note, assume ws_xpixel and ws_ypixel are zero. - s = struct.pack('HHHH', rows, cols, 0, 0) - fcntl.ioctl(fd, TIOCSWINSZ, s) - -class PtyProcess(object): - '''This class represents a process running in a pseudoterminal. - - The main constructor is the :meth:`spawn` classmethod. - ''' - string_type = bytes - if PY3: - linesep = os.linesep.encode('ascii') - crlf = '\r\n'.encode('ascii') - - @staticmethod - def write_to_stdout(b): - try: - return sys.stdout.buffer.write(b) - except AttributeError: - # If stdout has been replaced, it may not have .buffer - return sys.stdout.write(b.decode('ascii', 'replace')) - else: - linesep = os.linesep - crlf = '\r\n' - write_to_stdout = sys.stdout.write - - encoding = None - - argv = None - env = None - launch_dir = None - - def __init__(self, pid, fd): - _make_eof_intr() # Ensure _EOF and _INTR are calculated - self.pid = pid - self.fd = fd - readf = io.open(fd, 'rb', buffering=0) - writef = io.open(fd, 'wb', buffering=0, closefd=False) - self.fileobj = io.BufferedRWPair(readf, writef) - - self.terminated = False - self.closed = False - self.exitstatus = None - self.signalstatus = None - # status returned by os.waitpid - self.status = None - self.flag_eof = False - # Used by close() to give kernel time to update process status. - # Time in seconds. - self.delayafterclose = 0.1 - # Used by terminate() to give kernel time to update process status. - # Time in seconds. - self.delayafterterminate = 0.1 - - @classmethod - def spawn( - cls, argv, cwd=None, env=None, echo=True, preexec_fn=None, - dimensions=(24, 80)): - '''Start the given command in a child process in a pseudo terminal. - - This does all the fork/exec type of stuff for a pty, and returns an - instance of PtyProcess. - - If preexec_fn is supplied, it will be called with no arguments in the - child process before exec-ing the specified command. - It may, for instance, set signal handlers to SIG_DFL or SIG_IGN. - - Dimensions of the psuedoterminal used for the subprocess can be - specified as a tuple (rows, cols), or the default (24, 80) will be used. - ''' - # Note that it is difficult for this method to fail. - # You cannot detect if the child process cannot start. - # So the only way you can tell if the child process started - # or not is to try to read from the file descriptor. If you get - # EOF immediately then it means that the child is already dead. - # That may not necessarily be bad because you may have spawned a child - # that performs some task; creates no stdout output; and then dies. - - if not isinstance(argv, (list, tuple)): - raise TypeError("Expected a list or tuple for argv, got %r" % argv) - - # Shallow copy of argv so we can modify it - argv = argv[:] - command = argv[0] - - command_with_path = which(command) - if command_with_path is None: - raise FileNotFoundError('The command was not found or was not ' + - 'executable: %s.' % command) - command = command_with_path - argv[0] = command - - # [issue #119] To prevent the case where exec fails and the user is - # stuck interacting with a python child process instead of whatever - # was expected, we implement the solution from - # http://stackoverflow.com/a/3703179 to pass the exception to the - # parent process - - # [issue #119] 1. Before forking, open a pipe in the parent process. - exec_err_pipe_read, exec_err_pipe_write = os.pipe() - - if use_native_pty_fork: - pid, fd = pty.fork() - else: - # Use internal fork_pty, for Solaris - pid, fd = _fork_pty.fork_pty() - - # Some platforms must call setwinsize() and setecho() from the - # child process, and others from the primary process. We do both, - # allowing IOError for either. - - if pid == CHILD: - # set window size - try: - _setwinsize(STDIN_FILENO, *dimensions) - except IOError as err: - if err.args[0] not in (errno.EINVAL, errno.ENOTTY): - raise - - # disable echo if spawn argument echo was unset - if not echo: - try: - _setecho(STDIN_FILENO, False) - except (IOError, termios.error) as err: - if err.args[0] not in (errno.EINVAL, errno.ENOTTY): - raise - - # [issue #119] 3. The child closes the reading end and sets the - # close-on-exec flag for the writing end. - os.close(exec_err_pipe_read) - fcntl.fcntl(exec_err_pipe_write, fcntl.F_SETFD, fcntl.FD_CLOEXEC) - - # Do not allow child to inherit open file descriptors from parent, - # with the exception of the exec_err_pipe_write of the pipe - # Impose ceiling on max_fd: AIX bugfix for users with unlimited - # nofiles where resource.RLIMIT_NOFILE is 2^63-1 and os.closerange() - # occasionally raises out of range error - max_fd = min(1048576, resource.getrlimit(resource.RLIMIT_NOFILE)[0]) - os.closerange(3, exec_err_pipe_write) - os.closerange(exec_err_pipe_write+1, max_fd) - - if cwd is not None: - os.chdir(cwd) - - if preexec_fn is not None: - try: - preexec_fn() - except Exception as e: - ename = type(e).__name__ - tosend = '{}:0:{}'.format(ename, str(e)) - if PY3: - tosend = tosend.encode('utf-8') - - os.write(exec_err_pipe_write, tosend) - os.close(exec_err_pipe_write) - os._exit(1) - - try: - if env is None: - os.execv(command, argv) - else: - os.execvpe(command, argv, env) - except OSError as err: - # [issue #119] 5. If exec fails, the child writes the error - # code back to the parent using the pipe, then exits. - tosend = 'OSError:{}:{}'.format(err.errno, str(err)) - if PY3: - tosend = tosend.encode('utf-8') - os.write(exec_err_pipe_write, tosend) - os.close(exec_err_pipe_write) - os._exit(os.EX_OSERR) - - # Parent - inst = cls(pid, fd) - - # Set some informational attributes - inst.argv = argv - if env is not None: - inst.env = env - if cwd is not None: - inst.launch_dir = cwd - - # [issue #119] 2. After forking, the parent closes the writing end - # of the pipe and reads from the reading end. - os.close(exec_err_pipe_write) - exec_err_data = os.read(exec_err_pipe_read, 4096) - os.close(exec_err_pipe_read) - - # [issue #119] 6. The parent reads eof (a zero-length read) if the - # child successfully performed exec, since close-on-exec made - # successful exec close the writing end of the pipe. Or, if exec - # failed, the parent reads the error code and can proceed - # accordingly. Either way, the parent blocks until the child calls - # exec. - if len(exec_err_data) != 0: - try: - errclass, errno_s, errmsg = exec_err_data.split(b':', 2) - exctype = getattr(builtins, errclass.decode('ascii'), Exception) - - exception = exctype(errmsg.decode('utf-8', 'replace')) - if exctype is OSError: - exception.errno = int(errno_s) - except: - raise Exception('Subprocess failed, got bad error data: %r' - % exec_err_data) - else: - raise exception - - try: - inst.setwinsize(*dimensions) - except IOError as err: - if err.args[0] not in (errno.EINVAL, errno.ENOTTY, errno.ENXIO): - raise - - return inst - - def __repr__(self): - clsname = type(self).__name__ - if self.argv is not None: - args = [repr(self.argv)] - if self.env is not None: - args.append("env=%r" % self.env) - if self.launch_dir is not None: - args.append("cwd=%r" % self.launch_dir) - - return "{}.spawn({})".format(clsname, ", ".join(args)) - - else: - return "{}(pid={}, fd={})".format(clsname, self.pid, self.fd) - - @staticmethod - def _coerce_send_string(s): - if not isinstance(s, bytes): - return s.encode('utf-8') - return s - - @staticmethod - def _coerce_read_string(s): - return s - - def __del__(self): - '''This makes sure that no system resources are left open. Python only - garbage collects Python objects. OS file descriptors are not Python - objects, so they must be handled explicitly. If the child file - descriptor was opened outside of this class (passed to the constructor) - then this does not close it. ''' - - if not self.closed: - # It is possible for __del__ methods to execute during the - # teardown of the Python VM itself. Thus self.close() may - # trigger an exception because os.close may be None. - try: - self.close() - # which exception, shouldn't we catch explicitly .. ? - except: - pass - - - def fileno(self): - '''This returns the file descriptor of the pty for the child. - ''' - return self.fd - - def close(self, force=True): - '''This closes the connection with the child application. Note that - calling close() more than once is valid. This emulates standard Python - behavior with files. Set force to True if you want to make sure that - the child is terminated (SIGKILL is sent if the child ignores SIGHUP - and SIGINT). ''' - if not self.closed: - self.flush() - self.fileobj.close() # Closes the file descriptor - # Give kernel time to update process status. - time.sleep(self.delayafterclose) - if self.isalive(): - if not self.terminate(force): - raise PtyProcessError('Could not terminate the child.') - self.fd = -1 - self.closed = True - #self.pid = None - - def flush(self): - '''This does nothing. It is here to support the interface for a - File-like object. ''' - - pass - - def isatty(self): - '''This returns True if the file descriptor is open and connected to a - tty(-like) device, else False. - - On SVR4-style platforms implementing streams, such as SunOS and HP-UX, - the child pty may not appear as a terminal device. This means - methods such as setecho(), setwinsize(), getwinsize() may raise an - IOError. ''' - - return os.isatty(self.fd) - - def waitnoecho(self, timeout=None): - '''This waits until the terminal ECHO flag is set False. This returns - True if the echo mode is off. This returns False if the ECHO flag was - not set False before the timeout. This can be used to detect when the - child is waiting for a password. Usually a child application will turn - off echo mode when it is waiting for the user to enter a password. For - example, instead of expecting the "password:" prompt you can wait for - the child to set ECHO off:: - - p = pexpect.spawn('ssh user@example.com') - p.waitnoecho() - p.sendline(mypassword) - - If timeout==None then this method to block until ECHO flag is False. - ''' - - if timeout is not None: - end_time = time.time() + timeout - while True: - if not self.getecho(): - return True - if timeout < 0 and timeout is not None: - return False - if timeout is not None: - timeout = end_time - time.time() - time.sleep(0.1) - - def getecho(self): - '''This returns the terminal echo mode. This returns True if echo is - on or False if echo is off. Child applications that are expecting you - to enter a password often set ECHO False. See waitnoecho(). - - Not supported on platforms where ``isatty()`` returns False. ''' - - try: - attr = termios.tcgetattr(self.fd) - except termios.error as err: - errmsg = 'getecho() may not be called on this platform' - if err.args[0] == errno.EINVAL: - raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg)) - raise - - self.echo = bool(attr[3] & termios.ECHO) - return self.echo - - def setecho(self, state): - '''This sets the terminal echo mode on or off. Note that anything the - child sent before the echo will be lost, so you should be sure that - your input buffer is empty before you call setecho(). For example, the - following will work as expected:: - - p = pexpect.spawn('cat') # Echo is on by default. - p.sendline('1234') # We expect see this twice from the child... - p.expect(['1234']) # ... once from the tty echo... - p.expect(['1234']) # ... and again from cat itself. - p.setecho(False) # Turn off tty echo - p.sendline('abcd') # We will set this only once (echoed by cat). - p.sendline('wxyz') # We will set this only once (echoed by cat) - p.expect(['abcd']) - p.expect(['wxyz']) - - The following WILL NOT WORK because the lines sent before the setecho - will be lost:: - - p = pexpect.spawn('cat') - p.sendline('1234') - p.setecho(False) # Turn off tty echo - p.sendline('abcd') # We will set this only once (echoed by cat). - p.sendline('wxyz') # We will set this only once (echoed by cat) - p.expect(['1234']) - p.expect(['1234']) - p.expect(['abcd']) - p.expect(['wxyz']) - - - Not supported on platforms where ``isatty()`` returns False. - ''' - _setecho(self.fd, state) - - self.echo = state - - def read(self, size=1024): - """Read and return at most ``size`` bytes from the pty. - - Can block if there is nothing to read. Raises :exc:`EOFError` if the - terminal was closed. - - Unlike Pexpect's ``read_nonblocking`` method, this doesn't try to deal - with the vagaries of EOF on platforms that do strange things, like IRIX - or older Solaris systems. It handles the errno=EIO pattern used on - Linux, and the empty-string return used on BSD platforms and (seemingly) - on recent Solaris. - """ - try: - s = self.fileobj.read1(size) - except (OSError, IOError) as err: - if err.args[0] == errno.EIO: - # Linux-style EOF - self.flag_eof = True - raise EOFError('End Of File (EOF). Exception style platform.') - raise - if s == b'': - # BSD-style EOF (also appears to work on recent Solaris (OpenIndiana)) - self.flag_eof = True - raise EOFError('End Of File (EOF). Empty string style platform.') - - return s - - def readline(self): - """Read one line from the pseudoterminal, and return it as unicode. - - Can block if there is nothing to read. Raises :exc:`EOFError` if the - terminal was closed. - """ - try: - s = self.fileobj.readline() - except (OSError, IOError) as err: - if err.args[0] == errno.EIO: - # Linux-style EOF - self.flag_eof = True - raise EOFError('End Of File (EOF). Exception style platform.') - raise - if s == b'': - # BSD-style EOF (also appears to work on recent Solaris (OpenIndiana)) - self.flag_eof = True - raise EOFError('End Of File (EOF). Empty string style platform.') - - return s - - def _writeb(self, b, flush=True): - n = self.fileobj.write(b) - if flush: - self.fileobj.flush() - return n - - def write(self, s, flush=True): - """Write bytes to the pseudoterminal. - - Returns the number of bytes written. - """ - return self._writeb(s, flush=flush) - - def sendcontrol(self, char): - '''Helper method that wraps send() with mnemonic access for sending control - character to the child (such as Ctrl-C or Ctrl-D). For example, to send - Ctrl-G (ASCII 7, bell, '\a'):: - - child.sendcontrol('g') - - See also, sendintr() and sendeof(). - ''' - char = char.lower() - a = ord(char) - if 97 <= a <= 122: - a = a - ord('a') + 1 - byte = _byte(a) - return self._writeb(byte), byte - d = {'@': 0, '`': 0, - '[': 27, '{': 27, - '\\': 28, '|': 28, - ']': 29, '}': 29, - '^': 30, '~': 30, - '_': 31, - '?': 127} - if char not in d: - return 0, b'' - - byte = _byte(d[char]) - return self._writeb(byte), byte - - def sendeof(self): - '''This sends an EOF to the child. This sends a character which causes - the pending parent output buffer to be sent to the waiting child - program without waiting for end-of-line. If it is the first character - of the line, the read() in the user program returns 0, which signifies - end-of-file. This means to work as expected a sendeof() has to be - called at the beginning of a line. This method does not send a newline. - It is the responsibility of the caller to ensure the eof is sent at the - beginning of a line. ''' - - return self._writeb(_EOF), _EOF - - def sendintr(self): - '''This sends a SIGINT to the child. It does not require - the SIGINT to be the first character on a line. ''' - - return self._writeb(_INTR), _INTR - - def eof(self): - '''This returns True if the EOF exception was ever raised. - ''' - - return self.flag_eof - - def terminate(self, force=False): - '''This forces a child process to terminate. It starts nicely with - SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This - returns True if the child was terminated. This returns False if the - child could not be terminated. ''' - - if not self.isalive(): - return True - try: - self.kill(signal.SIGHUP) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - self.kill(signal.SIGCONT) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - self.kill(signal.SIGINT) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - if force: - self.kill(signal.SIGKILL) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - else: - return False - return False - except OSError: - # I think there are kernel timing issues that sometimes cause - # this to happen. I think isalive() reports True, but the - # process is dead to the kernel. - # Make one last attempt to see if the kernel is up to date. - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - else: - return False - - def wait(self): - '''This waits until the child exits. This is a blocking call. This will - not read any data from the child, so this will block forever if the - child has unread output and has terminated. In other words, the child - may have printed output then called exit(), but, the child is - technically still alive until its output is read by the parent. ''' - - if self.isalive(): - pid, status = os.waitpid(self.pid, 0) - else: - return self.exitstatus - self.exitstatus = os.WEXITSTATUS(status) - if os.WIFEXITED(status): - self.status = status - self.exitstatus = os.WEXITSTATUS(status) - self.signalstatus = None - self.terminated = True - elif os.WIFSIGNALED(status): - self.status = status - self.exitstatus = None - self.signalstatus = os.WTERMSIG(status) - self.terminated = True - elif os.WIFSTOPPED(status): # pragma: no cover - # You can't call wait() on a child process in the stopped state. - raise PtyProcessError('Called wait() on a stopped child ' + - 'process. This is not supported. Is some other ' + - 'process attempting job control with our child pid?') - return self.exitstatus - - def isalive(self): - '''This tests if the child process is running or not. This is - non-blocking. If the child was terminated then this will read the - exitstatus or signalstatus of the child. This returns True if the child - process appears to be running or False if not. It can take literally - SECONDS for Solaris to return the right status. ''' - - if self.terminated: - return False - - if self.flag_eof: - # This is for Linux, which requires the blocking form - # of waitpid to get the status of a defunct process. - # This is super-lame. The flag_eof would have been set - # in read_nonblocking(), so this should be safe. - waitpid_options = 0 - else: - waitpid_options = os.WNOHANG - - try: - pid, status = os.waitpid(self.pid, waitpid_options) - except OSError as e: - # No child processes - if e.errno == errno.ECHILD: - raise PtyProcessError('isalive() encountered condition ' + - 'where "terminated" is 0, but there was no child ' + - 'process. Did someone else call waitpid() ' + - 'on our process?') - else: - raise - - # I have to do this twice for Solaris. - # I can't even believe that I figured this out... - # If waitpid() returns 0 it means that no child process - # wishes to report, and the value of status is undefined. - if pid == 0: - try: - ### os.WNOHANG) # Solaris! - pid, status = os.waitpid(self.pid, waitpid_options) - except OSError as e: # pragma: no cover - # This should never happen... - if e.errno == errno.ECHILD: - raise PtyProcessError('isalive() encountered condition ' + - 'that should never happen. There was no child ' + - 'process. Did someone else call waitpid() ' + - 'on our process?') - else: - raise - - # If pid is still 0 after two calls to waitpid() then the process - # really is alive. This seems to work on all platforms, except for - # Irix which seems to require a blocking call on waitpid or select, - # so I let read_nonblocking take care of this situation - # (unfortunately, this requires waiting through the timeout). - if pid == 0: - return True - - if pid == 0: - return True - - if os.WIFEXITED(status): - self.status = status - self.exitstatus = os.WEXITSTATUS(status) - self.signalstatus = None - self.terminated = True - elif os.WIFSIGNALED(status): - self.status = status - self.exitstatus = None - self.signalstatus = os.WTERMSIG(status) - self.terminated = True - elif os.WIFSTOPPED(status): - raise PtyProcessError('isalive() encountered condition ' + - 'where child process is stopped. This is not ' + - 'supported. Is some other process attempting ' + - 'job control with our child pid?') - return False - - def kill(self, sig): - """Send the given signal to the child application. - - In keeping with UNIX tradition it has a misleading name. It does not - necessarily kill the child unless you send the right signal. See the - :mod:`signal` module for constants representing signal numbers. - """ - - # Same as os.kill, but the pid is given for you. - if self.isalive(): - os.kill(self.pid, sig) - - def getwinsize(self): - """Return the window size of the pseudoterminal as a tuple (rows, cols). - """ - TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912) - s = struct.pack('HHHH', 0, 0, 0, 0) - x = fcntl.ioctl(self.fd, TIOCGWINSZ, s) - return struct.unpack('HHHH', x)[0:2] - - def setwinsize(self, rows, cols): - """Set the terminal window size of the child tty. - - This will cause a SIGWINCH signal to be sent to the child. This does not - change the physical window size. It changes the size reported to - TTY-aware applications like vi or curses -- applications that respond to - the SIGWINCH signal. - """ - return _setwinsize(self.fd, rows, cols) - - -class PtyProcessUnicode(PtyProcess): - """Unicode wrapper around a process running in a pseudoterminal. - - This class exposes a similar interface to :class:`PtyProcess`, but its read - methods return unicode, and its :meth:`write` accepts unicode. - """ - if PY3: - string_type = str - else: - string_type = unicode # analysis:ignore - - def __init__(self, pid, fd, encoding='utf-8', codec_errors='strict'): - super(PtyProcessUnicode, self).__init__(pid, fd) - self.encoding = encoding - self.codec_errors = codec_errors - self.decoder = codecs.getincrementaldecoder(encoding)(errors=codec_errors) - - def read(self, size=1024): - """Read at most ``size`` bytes from the pty, return them as unicode. - - Can block if there is nothing to read. Raises :exc:`EOFError` if the - terminal was closed. - - The size argument still refers to bytes, not unicode code points. - """ - b = super(PtyProcessUnicode, self).read(size) - return self.decoder.decode(b, final=False) - - def readline(self): - """Read one line from the pseudoterminal, and return it as unicode. - - Can block if there is nothing to read. Raises :exc:`EOFError` if the - terminal was closed. - """ - b = super(PtyProcessUnicode, self).readline() - return self.decoder.decode(b, final=False) - - def write(self, s): - """Write the unicode string ``s`` to the pseudoterminal. - - Returns the number of bytes written. - """ - b = s.encode(self.encoding) - return super(PtyProcessUnicode, self).write(b) diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py b/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py deleted file mode 100644 index aadbd62c801d..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py +++ /dev/null @@ -1,71 +0,0 @@ -try: - from shutil import which # Python >= 3.3 -except ImportError: - import os, sys - - # This is copied from Python 3.4.1 - def which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - - """ - # Check that a given file can be accessed with the correct mode. - # Additionally check that `file` is not a directory, as on Windows - # directories pass the os.access check. - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) - and not os.path.isdir(fn)) - - # If we're given a path with a directory part, look it up directly rather - # than referring to PATH directories. This includes checking relative to the - # current directory, e.g. ./script - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", os.defpath) - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - # The current directory takes precedence on Windows. - if not os.curdir in path: - path.insert(0, os.curdir) - - # PATHEXT is necessary to check on Windows. - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - # See if the given file matches any of the expected path extensions. - # This will allow us to short circuit when given "python.exe". - # If it does match, only test that one, otherwise we have to try - # others. - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - # On other platforms you don't have things like PATHEXT to tell you - # what file suffixes are executable, so just pass on cmd as-is. - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if not normdir in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None - - -class PtyProcessError(Exception): - """Generic error class for this package.""" diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/pyproject.toml b/lldb/third_party/Python/module/ptyprocess-0.6.0/pyproject.toml deleted file mode 100644 index 881c1bae897d..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/pyproject.toml +++ /dev/null @@ -1,24 +0,0 @@ -[build-system] -requires = ["flit"] -build-backend = "flit.buildapi" - -[tool.flit.metadata] -module = "ptyprocess" -author = "Thomas Kluyver" -author-email = "thomas@kluyver.me.uk" -home-page = "https://github.com/pexpect/ptyprocess" -description-file = "README.rst" -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Environment :: Console", - "Intended Audience :: Developers", - "Intended Audience :: System Administrators", - "License :: OSI Approved :: ISC License (ISCL)", - "Operating System :: POSIX", - "Operating System :: MacOS :: MacOS X", - "Programming Language :: Python", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Topic :: Terminals" -] - diff --git a/lldb/third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml b/lldb/third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml deleted file mode 100644 index 8b77f690a1bb..000000000000 --- a/lldb/third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml +++ /dev/null @@ -1,2 +0,0 @@ -python: - version: 3 -- GitLab From 9a3595167d3ee875e3180800cec5f5c3fd170e63 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 22 Apr 2024 11:40:48 -0700 Subject: [PATCH 206/357] [RISCV] Add freeze when expanding mul by constant to two or more uses (#89290) topperc pointed this out in review of https://github.com/llvm/llvm-project/pull/88791, but I believe the problem applies here as well. Worth noting is that the code I introduced with this bug was mostly copied from other targets - which also have this bug. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 23 +++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 82339dd20721..41483c49ae03 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -13430,10 +13430,11 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG, if (ScaleShift >= 1 && ScaleShift < 4) { unsigned ShiftAmt = Log2_64((MulAmt & (MulAmt - 1))); SDLoc DL(N); - SDValue Shift1 = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), - DAG.getConstant(ShiftAmt, DL, VT)); - SDValue Shift2 = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), - DAG.getConstant(ScaleShift, DL, VT)); + SDValue X = DAG.getFreeze(N->getOperand(0)); + SDValue Shift1 = + DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShiftAmt, DL, VT)); + SDValue Shift2 = + DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ScaleShift, DL, VT)); return DAG.getNode(ISD::ADD, DL, VT, Shift1, Shift2); } } @@ -13464,13 +13465,13 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG, if (ScaleShift >= 1 && ScaleShift < 4) { unsigned ShiftAmt = Log2_64(((MulAmt - 1) & (MulAmt - 2))); SDLoc DL(N); - SDValue Shift1 = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), - DAG.getConstant(ShiftAmt, DL, VT)); - SDValue Shift2 = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), - DAG.getConstant(ScaleShift, DL, VT)); - return DAG.getNode( - ISD::ADD, DL, VT, Shift1, - DAG.getNode(ISD::ADD, DL, VT, Shift2, N->getOperand(0))); + SDValue X = DAG.getFreeze(N->getOperand(0)); + SDValue Shift1 = + DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShiftAmt, DL, VT)); + SDValue Shift2 = + DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ScaleShift, DL, VT)); + return DAG.getNode(ISD::ADD, DL, VT, Shift1, + DAG.getNode(ISD::ADD, DL, VT, Shift2, X)); } } -- GitLab From ca1f1c957232b05d6529916bcd769ae1c57ff935 Mon Sep 17 00:00:00 2001 From: js324 Date: Mon, 22 Apr 2024 14:42:57 -0400 Subject: [PATCH 207/357] [BitInt] Expose a _BitInt literal suffix in C++ (#86586) This exposes _BitInt literal suffixes __wb and u__wb as an extension in C++. There is a new Extension warning, and the tests are essentially the same as the existing _BitInt literal tests for C but with a few additional cases. Fixes #85223 --- clang/docs/ReleaseNotes.rst | 1 + .../clang/Basic/DiagnosticCommonKinds.td | 3 + clang/include/clang/Basic/DiagnosticGroups.td | 3 + .../clang/Basic/DiagnosticParseKinds.td | 2 +- clang/include/clang/Lex/LiteralSupport.h | 3 +- clang/lib/Lex/LiteralSupport.cpp | 36 +++- clang/lib/Lex/PPExpressions.cpp | 8 +- clang/lib/Sema/SemaExpr.cpp | 12 +- clang/test/AST/bitint-suffix.cpp | 32 ++++ clang/test/Lexer/bitint-constants-compat.c | 11 +- clang/test/Lexer/bitint-constants.cpp | 178 ++++++++++++++++++ 11 files changed, 273 insertions(+), 16 deletions(-) create mode 100644 clang/test/AST/bitint-suffix.cpp create mode 100644 clang/test/Lexer/bitint-constants.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b5b351f3d30a..2b3bafa1c305 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -88,6 +88,7 @@ sections with improvements to Clang's support for those languages. C++ Language Changes -------------------- +- Implemented ``_BitInt`` literal suffixes ``__wb`` or ``__WB`` as a Clang extension with ``unsigned`` modifiers also allowed. (#GH85223). C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index a52bf62e2420..0738f43ca555 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -234,6 +234,9 @@ def err_cxx23_size_t_suffix: Error< def err_size_t_literal_too_large: Error< "%select{signed |}0'size_t' literal is out of range of possible " "%select{signed |}0'size_t' values">; +def ext_cxx_bitint_suffix : Extension< + "'_BitInt' suffix for literals is a Clang extension">, + InGroup; def ext_c23_bitint_suffix : ExtWarn< "'_BitInt' suffix for literals is a C23 extension">, InGroup; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 47747d8704b6..60f87da2a738 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1520,5 +1520,8 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon // Warnings and notes InstallAPI verification. def InstallAPIViolation : DiagGroup<"installapi-violation">; +// Warnings related to _BitInt extension +def BitIntExtension : DiagGroup<"bit-int-extension">; + // Warnings about misuse of ExtractAPI options. def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 66405095d51d..38174cf3549f 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1654,7 +1654,7 @@ def warn_ext_int_deprecated : Warning< "'_ExtInt' is deprecated; use '_BitInt' instead">, InGroup; def ext_bit_int : Extension< "'_BitInt' in %select{C17 and earlier|C++}0 is a Clang extension">, - InGroup>; + InGroup; } // end of Parse Issue category. let CategoryName = "Modules Issue" in { diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 643ddbdad8c8..2ed42d1c5f9a 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -80,7 +80,8 @@ public: bool isFloat128 : 1; // 1.0q bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk - bool isBitInt : 1; // 1wb, 1uwb (C23) + bool isBitInt : 1; // 1wb, 1uwb (C23) or 1__wb, 1__uwb (Clang extension in C++ + // mode) uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 438c6d772e6e..9c0cbea5052c 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -974,6 +974,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, bool isFixedPointConstant = isFixedPointLiteral(); bool isFPConstant = isFloatingLiteral(); bool HasSize = false; + bool DoubleUnderscore = false; // Loop over all of the characters of the suffix. If we see something bad, // we break out of the loop. @@ -1117,6 +1118,31 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (isImaginary) break; // Cannot be repeated. isImaginary = true; continue; // Success. + case '_': + if (isFPConstant) + break; // Invalid for floats + if (HasSize) + break; + if (DoubleUnderscore) + break; // Cannot be repeated. + if (LangOpts.CPlusPlus && s + 2 < ThisTokEnd && + s[1] == '_') { // s + 2 < ThisTokEnd to ensure some character exists + // after __ + DoubleUnderscore = true; + s += 2; // Skip both '_' + if (s + 1 < ThisTokEnd && + (*s == 'u' || *s == 'U')) { // Ensure some character after 'u'/'U' + isUnsigned = true; + ++s; + } + if (s + 1 < ThisTokEnd && + ((*s == 'w' && *(++s) == 'b') || (*s == 'W' && *(++s) == 'B'))) { + isBitInt = true; + HasSize = true; + continue; + } + } + break; case 'w': case 'W': if (isFPConstant) @@ -1127,9 +1153,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // wb and WB are allowed, but a mixture of cases like Wb or wB is not. We // explicitly do not support the suffix in C++ as an extension because a // library-based UDL that resolves to a library type may be more - // appropriate there. - if (!LangOpts.CPlusPlus && ((s[0] == 'w' && s[1] == 'b') || - (s[0] == 'W' && s[1] == 'B'))) { + // appropriate there. The same rules apply for __wb/__WB. + if ((!LangOpts.CPlusPlus || DoubleUnderscore) && s + 1 < ThisTokEnd && + ((s[0] == 'w' && s[1] == 'b') || (s[0] == 'W' && s[1] == 'B'))) { isBitInt = true; HasSize = true; ++s; // Skip both characters (2nd char skipped on continue). @@ -1241,7 +1267,9 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, return false; // By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid. - if (Suffix[0] == '_') + // Suffixes starting with '__' (double underscore) are for use by + // the implementation. + if (Suffix.starts_with("_") && !Suffix.starts_with("__")) return true; // In C++11, there are no library suffixes. diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp index 8f25c67ec9df..f267efabd617 100644 --- a/clang/lib/Lex/PPExpressions.cpp +++ b/clang/lib/Lex/PPExpressions.cpp @@ -333,11 +333,11 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, : diag::ext_cxx23_size_t_suffix : diag::err_cxx23_size_t_suffix); - // 'wb/uwb' literals are a C23 feature. We explicitly do not support the - // suffix in C++ as an extension because a library-based UDL that resolves - // to a library type may be more appropriate there. + // 'wb/uwb' literals are a C23 feature. + // '__wb/__uwb' are a C++ extension. if (Literal.isBitInt) - PP.Diag(PeekTok, PP.getLangOpts().C23 + PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix + : PP.getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix : diag::ext_c23_bitint_suffix); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 092da4a75dc3..5c861467bc10 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4137,11 +4137,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // 'wb/uwb' literals are a C23 feature. We support _BitInt as a type in C++, // but we do not currently support the suffix in C++ mode because it's not // entirely clear whether WG21 will prefer this suffix to return a library - // type such as std::bit_int instead of returning a _BitInt. - if (Literal.isBitInt && !getLangOpts().CPlusPlus) - PP.Diag(Tok.getLocation(), getLangOpts().C23 - ? diag::warn_c23_compat_bitint_suffix - : diag::ext_c23_bitint_suffix); + // type such as std::bit_int instead of returning a _BitInt. '__wb/__uwb' + // literals are a C++ extension. + if (Literal.isBitInt) + PP.Diag(Tok.getLocation(), + getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix + : getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix + : diag::ext_c23_bitint_suffix); // Get the value in the widest-possible width. What is "widest" depends on // whether the literal is a bit-precise integer or not. For a bit-precise diff --git a/clang/test/AST/bitint-suffix.cpp b/clang/test/AST/bitint-suffix.cpp new file mode 100644 index 000000000000..dab2b16c7423 --- /dev/null +++ b/clang/test/AST/bitint-suffix.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -ast-dump -Wno-unused %s | FileCheck --strict-whitespace %s + +// CHECK: FunctionDecl 0x{{[^ ]*}} <{{.*}}:[[@LINE+1]]:1, line:{{[0-9]*}}:1> line:[[@LINE+1]]:6 func 'void ()' +void func() { + // Ensure that we calculate the correct type from the literal suffix. + + // Note: 0__wb should create an _BitInt(2) because a signed bit-precise + // integer requires one bit for the sign and one bit for the value, + // at a minimum. + // CHECK: TypedefDecl 0x{{[^ ]*}} col:29 zero_wb 'typeof (0wb)':'_BitInt(2)' + typedef __typeof__(0__wb) zero_wb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 neg_zero_wb 'typeof (-0wb)':'_BitInt(2)' + typedef __typeof__(-0__wb) neg_zero_wb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:29 one_wb 'typeof (1wb)':'_BitInt(2)' + typedef __typeof__(1__wb) one_wb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 neg_one_wb 'typeof (-1wb)':'_BitInt(2)' + typedef __typeof__(-1__wb) neg_one_wb; + + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 zero_uwb 'typeof (0uwb)':'unsigned _BitInt(1)' + typedef __typeof__(0__uwb) zero_uwb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:31 neg_zero_uwb 'typeof (-0uwb)':'unsigned _BitInt(1)' + typedef __typeof__(-0__uwb) neg_zero_uwb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:30 one_uwb 'typeof (1uwb)':'unsigned _BitInt(1)' + typedef __typeof__(1__uwb) one_uwb; + + // Try a value that is too large to fit in [u]intmax_t. + + // CHECK: TypedefDecl 0x{{[^ ]*}} col:49 huge_uwb 'typeof (18446744073709551616uwb)':'unsigned _BitInt(65)' + typedef __typeof__(18446744073709551616__uwb) huge_uwb; + // CHECK: TypedefDecl 0x{{[^ ]*}} col:48 huge_wb 'typeof (18446744073709551616wb)':'_BitInt(66)' + typedef __typeof__(18446744073709551616__wb) huge_wb; +} diff --git a/clang/test/Lexer/bitint-constants-compat.c b/clang/test/Lexer/bitint-constants-compat.c index 607ae88a6188..d8bff94ef88c 100644 --- a/clang/test/Lexer/bitint-constants-compat.c +++ b/clang/test/Lexer/bitint-constants-compat.c @@ -1,14 +1,23 @@ // RUN: %clang_cc1 -std=c17 -fsyntax-only -verify=ext -Wno-unused %s // RUN: %clang_cc1 -std=c2x -fsyntax-only -verify=compat -Wpre-c2x-compat -Wno-unused %s -// RUN: %clang_cc1 -fsyntax-only -verify=cpp -Wno-unused -x c++ %s +// RUN: %clang_cc1 -fsyntax-only -verify=cpp -Wbit-int-extension -Wno-unused -x c++ %s #if 18446744073709551615uwb // ext-warning {{'_BitInt' suffix for literals is a C23 extension}} \ compat-warning {{'_BitInt' suffix for literals is incompatible with C standards before C23}} \ cpp-error {{invalid suffix 'uwb' on integer constant}} #endif +#if 18446744073709551615__uwb // ext-error {{invalid suffix '__uwb' on integer constant}} \ + compat-error {{invalid suffix '__uwb' on integer constant}} \ + cpp-warning {{'_BitInt' suffix for literals is a Clang extension}} +#endif + void func(void) { 18446744073709551615wb; // ext-warning {{'_BitInt' suffix for literals is a C23 extension}} \ compat-warning {{'_BitInt' suffix for literals is incompatible with C standards before C23}} \ cpp-error {{invalid suffix 'wb' on integer constant}} + + 18446744073709551615__wb; // ext-error {{invalid suffix '__wb' on integer constant}} \ + compat-error {{invalid suffix '__wb' on integer constant}} \ + cpp-warning {{'_BitInt' suffix for literals is a Clang extension}} } diff --git a/clang/test/Lexer/bitint-constants.cpp b/clang/test/Lexer/bitint-constants.cpp new file mode 100644 index 000000000000..fb6ac35467cd --- /dev/null +++ b/clang/test/Lexer/bitint-constants.cpp @@ -0,0 +1,178 @@ +// RUN: %clang_cc1 -triple aarch64-unknown-unknown -fsyntax-only -verify -Wno-unused %s + +// Test that the preprocessor behavior makes sense. +#if 1__wb != 1 +#error "wb suffix must be recognized by preprocessor" +#endif +#if 1__uwb != 1 +#error "uwb suffix must be recognized by preprocessor" +#endif +#if !(-1__wb < 0) +#error "wb suffix must be interpreted as signed" +#endif +#if !(-1__uwb > 0) +#error "uwb suffix must be interpreted as unsigned" +#endif + +#if 18446744073709551615__uwb != 18446744073709551615ULL +#error "expected the max value for uintmax_t to compare equal" +#endif + +// Test that the preprocessor gives appropriate diagnostics when the +// literal value is larger than what can be stored in a [u]intmax_t. +#if 18446744073709551616__wb != 0ULL // expected-error {{integer literal is too large to be represented in any integer type}} +#error "never expected to get here due to error" +#endif +#if 18446744073709551616__uwb != 0ULL // expected-error {{integer literal is too large to be represented in any integer type}} +#error "never expected to get here due to error" +#endif + +// Despite using a bit-precise integer, this is expected to overflow +// because all preprocessor arithmetic is done in [u]intmax_t, so this +// should result in the value 0. +#if 18446744073709551615__uwb + 1 != 0ULL +#error "expected modulo arithmetic with uintmax_t width" +#endif + +// Because this bit-precise integer is signed, it will also overflow, +// but Clang handles that by converting to uintmax_t instead of +// intmax_t. +#if 18446744073709551615__wb + 1 != 0LL // expected-warning {{integer literal is too large to be represented in a signed integer type, interpreting as unsigned}} +#error "expected modulo arithmetic with uintmax_t width" +#endif + +// Test that just because the preprocessor can't figure out the bit +// width doesn't mean we can't form the constant, it just means we +// can't use the value in a preprocessor conditional. +unsigned _BitInt(65) Val = 18446744073709551616__uwb; +// UDL test to make sure underscore parsing is correct +unsigned operator ""_(const char *); + +void ValidSuffix(void) { + // Decimal literals. + 1__wb; + 1__WB; + -1__wb; + _Static_assert((int)1__wb == 1, "not 1?"); + _Static_assert((int)-1__wb == -1, "not -1?"); + + 1__uwb; + 1__uWB; + 1__Uwb; + 1__UWB; + 1u__wb; + 1__WBu; + 1U__WB; + _Static_assert((unsigned int)1__uwb == 1u, "not 1?"); + + 1'2__wb; + 1'2__uwb; + _Static_assert((int)1'2__wb == 12, "not 12?"); + _Static_assert((unsigned int)1'2__uwb == 12u, "not 12?"); + + // Hexadecimal literals. + 0x1__wb; + 0x1__uwb; + 0x0'1'2'3__wb; + 0xA'B'c'd__uwb; + _Static_assert((int)0x0'1'2'3__wb == 0x0123, "not 0x0123"); + _Static_assert((unsigned int)0xA'B'c'd__uwb == 0xABCDu, "not 0xABCD"); + + // Binary literals. + 0b1__wb; + 0b1__uwb; + 0b1'0'1'0'0'1__wb; + 0b0'1'0'1'1'0__uwb; + _Static_assert((int)0b1__wb == 1, "not 1?"); + _Static_assert((unsigned int)0b1__uwb == 1u, "not 1?"); + + // Octal literals. + 01__wb; + 01__uwb; + 0'6'0__wb; + 0'0'1__uwb; + 0__wbu; + 0__WBu; + 0U__wb; + 0U__WB; + 0__wb; + _Static_assert((int)0__wb == 0, "not 0?"); + _Static_assert((unsigned int)0__wbu == 0u, "not 0?"); + + // Imaginary or Complex. These are allowed because _Complex can work with any + // integer type, and that includes _BitInt. + 1__wbi; + 1i__wb; + 1__wbj; + + //UDL test as single underscore + unsigned i = 1.0_; +} + +void InvalidSuffix(void) { + // Can't mix the case of wb or WB, and can't rearrange the letters. + 0__wB; // expected-error {{invalid suffix '__wB' on integer constant}} + 0__Wb; // expected-error {{invalid suffix '__Wb' on integer constant}} + 0__bw; // expected-error {{invalid suffix '__bw' on integer constant}} + 0__BW; // expected-error {{invalid suffix '__BW' on integer constant}} + + // Trailing digit separators should still diagnose. + 1'2'__wb; // expected-error {{digit separator cannot appear at end of digit sequence}} + 1'2'__uwb; // expected-error {{digit separator cannot appear at end of digit sequence}} + + // Long. + 1l__wb; // expected-error {{invalid suffix}} + 1__wbl; // expected-error {{invalid suffix}} + 1l__uwb; // expected-error {{invalid suffix}} + 1__l; // expected-error {{invalid suffix}} + 1ul__wb; // expected-error {{invalid suffix}} + + // Long long. + 1ll__wb; // expected-error {{invalid suffix}} + 1__uwbll; // expected-error {{invalid suffix}} + + // Floating point. + 0.1__wb; // expected-error {{invalid suffix}} + 0.1f__wb; // expected-error {{invalid suffix}} + + // Repetitive suffix. + 1__wb__wb; // expected-error {{invalid suffix}} + 1__uwbuwb; // expected-error {{invalid suffix}} + 1__wbuwb; // expected-error {{invalid suffix}} + 1__uwbwb; // expected-error {{invalid suffix}} + + // Missing or extra characters in suffix. + 1__; // expected-error {{invalid suffix}} + 1__u; // expected-error {{invalid suffix}} + 1___; // expected-error {{invalid suffix}} + 1___WB; // expected-error {{invalid suffix}} + 1__wb__; // expected-error {{invalid suffix}} + 1__w; // expected-error {{invalid suffix}} + 1__b; // expected-error {{invalid suffix}} +} + +void ValidSuffixInvalidValue(void) { + // This is a valid suffix, but the value is larger than one that fits within + // the width of BITINT_MAXWIDTH. When this value changes in the future, the + // test cases should pick a new value that can't be represented by a _BitInt, + // but also add a test case that a 129-bit literal still behaves as-expected. + _Static_assert(__BITINT_MAXWIDTH__ <= 128, + "Need to pick a bigger constant for the test case below."); + 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1__wb; // expected-error {{integer literal is too large to be represented in any signed integer type}} + 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1__uwb; // expected-error {{integer literal is too large to be represented in any integer type}} +} + +void TestTypes(void) { + // 2 value bits, one sign bit + _Static_assert(__is_same(decltype(3__wb), _BitInt(3))); + // 2 value bits, one sign bit + _Static_assert(__is_same(decltype(-3__wb), _BitInt(3))); + // 2 value bits, no sign bit + _Static_assert(__is_same(decltype(3__uwb), unsigned _BitInt(2))); + // 4 value bits, one sign bit + _Static_assert(__is_same(decltype(0xF__wb), _BitInt(5))); + // 4 value bits, one sign bit + _Static_assert(__is_same(decltype(-0xF__wb), _BitInt(5))); + // 4 value bits, no sign bit + _Static_assert(__is_same(decltype(0xF__uwb), unsigned _BitInt(4))); +} -- GitLab From 43c26bbc425dbd8caee311a0d5e4d90c8e71d0d8 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Mon, 22 Apr 2024 11:50:59 -0700 Subject: [PATCH 208/357] [libc] don't over include stdlib in the hdr declaring bsearch (#89471) When building overlay mode with GCC in release mode, glibc's stdlib.h contains an extern inline declaration of bsearch. This breaks our use of the gnu::alias function attribute in LLVM_LIBC_FUNCTION with GCC because GCC checks that the aliasee is defined in the same TU (clang does not). We're looking at also potentially updating our definition of LLVM_LIBC_FUNCTION from libc/src/__support/common.h. Upon testing, I was able to get -Wnonnull-compare diagnostics from GCC in our definition of bsearch because glibc declares bsearch with the fugly nonnull function attribute. There's more we can do here though to improve our implementation of bsearch. 7.24.5.1 says: Pointer arguments on such a call shall still have valid values, as described in 7.1.4. We could also use either function attributes or parameter attributes to denote these should not be null (for users/callers) and perhaps still check for non-null explicitly under some yet to be discussed hardening configurations in the future. Link: #60481 Link: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute --- libc/src/stdlib/bsearch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/stdlib/bsearch.h b/libc/src/stdlib/bsearch.h index 1de7e051ff6c..3590198ba557 100644 --- a/libc/src/stdlib/bsearch.h +++ b/libc/src/stdlib/bsearch.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC_STDLIB_BSEARCH_H #define LLVM_LIBC_SRC_STDLIB_BSEARCH_H -#include +#include // size_t namespace LIBC_NAMESPACE { -- GitLab From a54102a093190f3a29add5d9327e62f13fce896a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Degioanni?= Date: Mon, 22 Apr 2024 20:54:22 +0200 Subject: [PATCH 209/357] [llvm] Add support for zero-width integers in MathExtras.h (#87193) MLIR uses zero-width integers, but also re-uses integer logic from LLVM to avoid duplication. This creates issues when LLVM logic is used in MLIR on integers which can be zero-width. In order to avoid special-casing the bitwidth-related logic in MLIR, this PR adds support for zero-width integers in LLVM's MathExtras (and consequently APInt). While most of the logic in theory works the same way out of the box, because bitshifting right by the entire bitwidth in C++ is undefined behavior instead of being zero, some special cases had to be added. Fortunately, it seems like the performance penalty is small. In x86, this usually yields the addition of a predicated conditional move. I checked that no branch is inserted in Arm too. This happens to fix a crash in `arith.extsi` canonicalization in MLIR. I think a follow-up PR to add tests for i0 in arith would be beneficial. --- llvm/include/llvm/Support/MathExtras.h | 58 ++++++++++++++--------- llvm/unittests/ADT/APIntTest.cpp | 3 ++ llvm/unittests/Support/MathExtrasTest.cpp | 8 ++++ 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index aa4f4d2ed42e..f0e4ee534ece 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -66,7 +66,9 @@ template T maskTrailingOnes(unsigned N) { static_assert(std::is_unsigned_v, "Invalid type!"); const unsigned Bits = CHAR_BIT * sizeof(T); assert(N <= Bits && "Invalid bit index"); - return N == 0 ? 0 : (T(-1) >> (Bits - N)); + if (N == 0) + return 0; + return T(-1) >> (Bits - N); } /// Create a bitmask with the N left-most bits set to 1, and all other @@ -149,6 +151,8 @@ constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { /// Checks if an integer fits into the given bit width. template constexpr inline bool isInt(int64_t x) { + if constexpr (N == 0) + return 0 == x; if constexpr (N == 8) return static_cast(x) == x; if constexpr (N == 16) @@ -164,15 +168,15 @@ template constexpr inline bool isInt(int64_t x) { /// Checks if a signed integer is an N bit number shifted left by S. template constexpr inline bool isShiftedInt(int64_t x) { - static_assert( - N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number."); + static_assert(S < 64, "isShiftedInt with S >= 64 is too much."); static_assert(N + S <= 64, "isShiftedInt with N + S > 64 is too wide."); return isInt(x) && (x % (UINT64_C(1) << S) == 0); } /// Checks if an unsigned integer fits into the given bit width. template constexpr inline bool isUInt(uint64_t x) { - static_assert(N > 0, "isUInt<0> doesn't make sense"); + if constexpr (N == 0) + return 0 == x; if constexpr (N == 8) return static_cast(x) == x; if constexpr (N == 16) @@ -188,39 +192,46 @@ template constexpr inline bool isUInt(uint64_t x) { /// Checks if a unsigned integer is an N bit number shifted left by S. template constexpr inline bool isShiftedUInt(uint64_t x) { - static_assert( - N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)"); + static_assert(S < 64, "isShiftedUInt with S >= 64 is too much."); static_assert(N + S <= 64, "isShiftedUInt with N + S > 64 is too wide."); - // Per the two static_asserts above, S must be strictly less than 64. So - // 1 << S is not undefined behavior. + // S must be strictly less than 64. So 1 << S is not undefined behavior. return isUInt(x) && (x % (UINT64_C(1) << S) == 0); } /// Gets the maximum value for a N-bit unsigned integer. inline uint64_t maxUIntN(uint64_t N) { - assert(N > 0 && N <= 64 && "integer width out of range"); + assert(N <= 64 && "integer width out of range"); // uint64_t(1) << 64 is undefined behavior, so we can't do // (uint64_t(1) << N) - 1 // without checking first that N != 64. But this works and doesn't have a - // branch. + // branch for N != 0. + // Unfortunately, shifting a uint64_t right by 64 bit is undefined + // behavior, so the condition on N == 0 is necessary. Fortunately, most + // optimizers do not emit branches for this check. + if (N == 0) + return 0; return UINT64_MAX >> (64 - N); } /// Gets the minimum value for a N-bit signed integer. inline int64_t minIntN(int64_t N) { - assert(N > 0 && N <= 64 && "integer width out of range"); + assert(N <= 64 && "integer width out of range"); + if (N == 0) + return 0; return UINT64_C(1) + ~(UINT64_C(1) << (N - 1)); } /// Gets the maximum value for a N-bit signed integer. inline int64_t maxIntN(int64_t N) { - assert(N > 0 && N <= 64 && "integer width out of range"); + assert(N <= 64 && "integer width out of range"); // This relies on two's complement wraparound when N == 64, so we convert to // int64_t only at the very end to avoid UB. + if (N == 0) + return 0; return (UINT64_C(1) << (N - 1)) - 1; } @@ -432,34 +443,38 @@ inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { } /// Sign-extend the number in the bottom B bits of X to a 32-bit integer. -/// Requires 0 < B <= 32. +/// Requires B <= 32. template constexpr inline int32_t SignExtend32(uint32_t X) { - static_assert(B > 0, "Bit width can't be 0."); static_assert(B <= 32, "Bit width out of range."); + if constexpr (B == 0) + return 0; return int32_t(X << (32 - B)) >> (32 - B); } /// Sign-extend the number in the bottom B bits of X to a 32-bit integer. -/// Requires 0 < B <= 32. +/// Requires B <= 32. inline int32_t SignExtend32(uint32_t X, unsigned B) { - assert(B > 0 && "Bit width can't be 0."); assert(B <= 32 && "Bit width out of range."); + if (B == 0) + return 0; return int32_t(X << (32 - B)) >> (32 - B); } /// Sign-extend the number in the bottom B bits of X to a 64-bit integer. -/// Requires 0 < B <= 64. +/// Requires B <= 64. template constexpr inline int64_t SignExtend64(uint64_t x) { - static_assert(B > 0, "Bit width can't be 0."); static_assert(B <= 64, "Bit width out of range."); + if constexpr (B == 0) + return 0; return int64_t(x << (64 - B)) >> (64 - B); } /// Sign-extend the number in the bottom B bits of X to a 64-bit integer. -/// Requires 0 < B <= 64. +/// Requires B <= 64. inline int64_t SignExtend64(uint64_t X, unsigned B) { - assert(B > 0 && "Bit width can't be 0."); assert(B <= 64 && "Bit width out of range."); + if (B == 0) + return 0; return int64_t(X << (64 - B)) >> (64 - B); } @@ -564,7 +579,6 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { /// Use this rather than HUGE_VALF; the latter causes warnings on MSVC. extern const float huge_valf; - /// Add two signed integers, computing the two's complement truncated result, /// returning true if overflow occurred. template @@ -644,6 +658,6 @@ std::enable_if_t, T> MulOverflow(T X, T Y, T &Result) { return UX > (static_cast(std::numeric_limits::max())) / UY; } -} // End llvm namespace +} // namespace llvm #endif diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 76fc26412407..46aaa47ee645 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -2797,6 +2797,9 @@ TEST(APIntTest, sext) { EXPECT_EQ(63U, i32_neg1.countl_one()); EXPECT_EQ(0U, i32_neg1.countr_zero()); EXPECT_EQ(63U, i32_neg1.popcount()); + + EXPECT_EQ(APInt(32u, 0), APInt(0u, 0).sext(32)); + EXPECT_EQ(APInt(64u, 0), APInt(0u, 0).sext(64)); } TEST(APIntTest, trunc) { diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp index 72c765d9ba30..218655851ca0 100644 --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -41,6 +41,9 @@ TEST(MathExtras, onesMask) { TEST(MathExtras, isIntN) { EXPECT_TRUE(isIntN(16, 32767)); EXPECT_FALSE(isIntN(16, 32768)); + EXPECT_TRUE(isUIntN(0, 0)); + EXPECT_FALSE(isUIntN(0, 1)); + EXPECT_FALSE(isUIntN(0, -1)); } TEST(MathExtras, isUIntN) { @@ -48,6 +51,8 @@ TEST(MathExtras, isUIntN) { EXPECT_FALSE(isUIntN(16, 65536)); EXPECT_TRUE(isUIntN(1, 0)); EXPECT_TRUE(isUIntN(6, 63)); + EXPECT_TRUE(isUIntN(0, 0)); + EXPECT_FALSE(isUIntN(0, 1)); } TEST(MathExtras, maxIntN) { @@ -55,6 +60,7 @@ TEST(MathExtras, maxIntN) { EXPECT_EQ(2147483647, maxIntN(32)); EXPECT_EQ(std::numeric_limits::max(), maxIntN(32)); EXPECT_EQ(std::numeric_limits::max(), maxIntN(64)); + EXPECT_EQ(0, maxIntN(0)); } TEST(MathExtras, minIntN) { @@ -62,6 +68,7 @@ TEST(MathExtras, minIntN) { EXPECT_EQ(-64LL, minIntN(7)); EXPECT_EQ(std::numeric_limits::min(), minIntN(32)); EXPECT_EQ(std::numeric_limits::min(), minIntN(64)); + EXPECT_EQ(0, minIntN(0)); } TEST(MathExtras, maxUIntN) { @@ -70,6 +77,7 @@ TEST(MathExtras, maxUIntN) { EXPECT_EQ(0xffffffffffffffffULL, maxUIntN(64)); EXPECT_EQ(1ULL, maxUIntN(1)); EXPECT_EQ(0x0fULL, maxUIntN(4)); + EXPECT_EQ(0, maxUIntN(0)); } TEST(MathExtras, reverseBits) { -- GitLab From 0336116ed463c2ad125793a5aa4d7290a2155709 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Mon, 22 Apr 2024 11:57:28 -0700 Subject: [PATCH 210/357] [libc][docs] codify Policy on Assembler Sources (#88185) It would be helpful in future code reviews to document a policy with regards to where and when Assembler sources are appropriate. That way when reviewers point out infractions, they can point to this written policy, which may help contributors understand that it's not solely the personal preferences of individual reviewers but instead rather a previously agreed upon rule by maintainers. Link: https://github.com/llvm/llvm-project/pull/87837 Link: https://github.com/llvm/llvm-project/pull/88157 Link: https://discourse.llvm.org/t/hand-written-in-assembly-in-libc-setjmp-longjmp/73249/12 --- libc/docs/dev/code_style.rst | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/libc/docs/dev/code_style.rst b/libc/docs/dev/code_style.rst index ee4e4257c9fa..170ef6598a9d 100644 --- a/libc/docs/dev/code_style.rst +++ b/libc/docs/dev/code_style.rst @@ -219,3 +219,44 @@ defines. Code under ``libc/src/`` should ``#include`` a proxy header from ``hdr/``, which contains a guard on ``LLVM_LIBC_FULL_BUILD`` to either include our header from ``libc/include/`` (fullbuild) or the corresponding underlying system header (overlay). + +Policy on Assembly sources +========================== + +Coding in high level languages such as C++ provides benefits relative to low +level languages like Assembly, such as: + +* Improved safety +* Compile time diagnostics +* Instrumentation + + * Code coverage + * Profile collection +* Sanitization +* Automatic generation of debug info + +While it's not impossible to have Assembly code that correctly provides all of +the above, we do not wish to maintain such Assembly sources in llvm-libc. + +That said, there are a few functions provided by llvm-libc that are impossible +to reliably implement in C++ for all compilers supported for building +llvm-libc. + +We do use inline or out-of-line Assembly in an intentionally minimal set of +places; typically places where the stack or individual register state must be +manipulated very carefully for correctness, or instances where a specific +instruction sequence does not have a corresponding compiler builtin function +today. + +Contributions adding functions implemented purely in Assembly for performance +are not welcome. + +Contributors should strive to stick with C++ for as long as it remains +reasonable to do so. Ideally, bugs should be filed against compiler vendors, +and links to those bug reports should appear in commit messages or comments +that seek to add Assembly to llvm-libc. + +Patches containing any amount of Assembly ideally should be approved by 2 +maintainers. llvm-libc maintainers reserve the right to reject Assembly +contributions that they feel could be better maintained if rewritten in C++, +and to revisit this policy in the future. -- GitLab From dd7963239e94bcd46e56ae90b08d2d0c9904ff00 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Mon, 22 Apr 2024 12:03:27 -0700 Subject: [PATCH 211/357] [libc][POSIX][pthreads] implement pthread_rwlockattr_t functions (#89322) Implement: - pthread_rwlockattr_destroy - pthread_rwlockattr_getpshared - pthread_rwlockattr_init - pthread_rwlockattr_setpshared --- libc/config/linux/api.td | 6 +- libc/config/linux/x86_64/entrypoints.txt | 4 ++ libc/include/CMakeLists.txt | 5 +- libc/include/llvm-libc-types/CMakeLists.txt | 1 + .../llvm-libc-types/pthread_rwlockattr_t.h | 15 +++++ libc/spec/posix.td | 26 ++++++++ libc/src/pthread/CMakeLists.txt | 41 ++++++++++++ .../pthread/pthread_rwlockattr_destroy.cpp | 24 +++++++ libc/src/pthread/pthread_rwlockattr_destroy.h | 20 ++++++ .../pthread/pthread_rwlockattr_getpshared.cpp | 23 +++++++ .../pthread/pthread_rwlockattr_getpshared.h | 21 ++++++ libc/src/pthread/pthread_rwlockattr_init.cpp | 23 +++++++ libc/src/pthread/pthread_rwlockattr_init.h | 20 ++++++ .../pthread/pthread_rwlockattr_setpshared.cpp | 27 ++++++++ .../pthread/pthread_rwlockattr_setpshared.h | 20 ++++++ libc/test/src/pthread/CMakeLists.txt | 17 ++++- .../src/pthread/pthread_rwlockattr_test.cpp | 64 +++++++++++++++++++ 17 files changed, 352 insertions(+), 5 deletions(-) create mode 100644 libc/include/llvm-libc-types/pthread_rwlockattr_t.h create mode 100644 libc/src/pthread/pthread_rwlockattr_destroy.cpp create mode 100644 libc/src/pthread/pthread_rwlockattr_destroy.h create mode 100644 libc/src/pthread/pthread_rwlockattr_getpshared.cpp create mode 100644 libc/src/pthread/pthread_rwlockattr_getpshared.h create mode 100644 libc/src/pthread/pthread_rwlockattr_init.cpp create mode 100644 libc/src/pthread/pthread_rwlockattr_init.h create mode 100644 libc/src/pthread/pthread_rwlockattr_setpshared.cpp create mode 100644 libc/src/pthread/pthread_rwlockattr_setpshared.h create mode 100644 libc/test/src/pthread/pthread_rwlockattr_test.cpp diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index 5fb92a9c299c..7843513c4d27 100644 --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -176,11 +176,12 @@ def PThreadAPI : PublicAPI<"pthread.h"> { "__pthread_tss_dtor_t", "pthread_attr_t", "pthread_condattr_t", + "pthread_key_t", "pthread_mutex_t", "pthread_mutexattr_t", - "pthread_t", - "pthread_key_t", "pthread_once_t", + "pthread_rwlockattr_t", + "pthread_t", ]; } @@ -259,6 +260,7 @@ def SysTypesAPI : PublicAPI<"sys/types.h"> { "pthread_mutex_t", "pthread_mutexattr_t", "pthread_once_t", + "pthread_rwlockattr_t", "pthread_t", "size_t", "ssize_t", diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 2d8136536b21..a8e289927667 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -669,6 +669,10 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.pthread.pthread_mutexattr_setrobust libc.src.pthread.pthread_mutexattr_settype libc.src.pthread.pthread_once + libc.src.pthread.pthread_rwlockattr_destroy + libc.src.pthread.pthread_rwlockattr_getpshared + libc.src.pthread.pthread_rwlockattr_init + libc.src.pthread.pthread_rwlockattr_setpshared libc.src.pthread.pthread_setspecific # sched.h entrypoints diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index f5ba2791af3f..aeef46aabfce 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -322,11 +322,12 @@ add_gen_header( .llvm-libc-types.__pthread_tss_dtor_t .llvm-libc-types.pthread_attr_t .llvm-libc-types.pthread_condattr_t + .llvm-libc-types.pthread_key_t .llvm-libc-types.pthread_mutex_t .llvm-libc-types.pthread_mutexattr_t - .llvm-libc-types.pthread_t - .llvm-libc-types.pthread_key_t .llvm-libc-types.pthread_once_t + .llvm-libc-types.pthread_rwlockattr_t + .llvm-libc-types.pthread_t ) add_gen_header( diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index f26fc0729dc9..310374fb62ff 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -54,6 +54,7 @@ add_header(pthread_key_t HDR pthread_key_t.h) add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type) add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h) add_header(pthread_once_t HDR pthread_once_t.h DEPENDS .__futex_word) +add_header(pthread_rwlockattr_t HDR pthread_rwlockattr_t.h) add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type) add_header(rlim_t HDR rlim_t.h) add_header(time_t HDR time_t.h) diff --git a/libc/include/llvm-libc-types/pthread_rwlockattr_t.h b/libc/include/llvm-libc-types/pthread_rwlockattr_t.h new file mode 100644 index 000000000000..a63de4f7b438 --- /dev/null +++ b/libc/include/llvm-libc-types/pthread_rwlockattr_t.h @@ -0,0 +1,15 @@ +//===-- Definition of pthread_rwlockattr_t type ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_TYPES_PTHREAD_RWLOCKATTR_T_H +#define LLVM_LIBC_TYPES_PTHREAD_RWLOCKATTR_T_H + +typedef struct { + int pshared; +} pthread_rwlockattr_t; + +#endif // LLVM_LIBC_TYPES_PTHREAD_RWLOCKATTR_T_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 0c88dbd848a3..d428d54e32a3 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -110,6 +110,10 @@ def POSIX : StandardSpec<"POSIX"> { PtrType PThreadCondAttrTPtr = PtrType; ConstType ConstRestrictedPThreadCondAttrTPtr = ConstType>; + NamedType PThreadRWLockAttrTType = NamedType<"pthread_rwlockattr_t">; + PtrType PThreadRWLockAttrTPtr = PtrType; + ConstType ConstPThreadRWLockAttrTPtr = ConstType; + NamedType PThreadMutexAttrTType = NamedType<"pthread_mutexattr_t">; PtrType PThreadMutexAttrTPtr = PtrType; RestrictedPtrType RestrictedPThreadMutexAttrTPtr = RestrictedPtrType; @@ -993,6 +997,7 @@ def POSIX : StandardSpec<"POSIX"> { PThreadMutexTType, PThreadOnceCallback, PThreadOnceT, + PThreadRWLockAttrTType, PThreadStartT, PThreadTSSDtorT, PThreadTType, @@ -1219,6 +1224,26 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec, ArgSpec] >, + FunctionSpec< + "pthread_rwlockattr_destroy", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "pthread_rwlockattr_getpshared", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "pthread_rwlockattr_init", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "pthread_rwlockattr_setpshared", + RetValSpec, + [ArgSpec, ArgSpec] + >, ] >; @@ -1575,6 +1600,7 @@ def POSIX : StandardSpec<"POSIX"> { PThreadMutexAttrTType, PThreadMutexTType, PThreadOnceT, + PThreadRWLockAttrTType, PThreadTType, PidT, SSizeTType, diff --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt index 3d6cf6dde010..c57475c9114f 100644 --- a/libc/src/pthread/CMakeLists.txt +++ b/libc/src/pthread/CMakeLists.txt @@ -460,6 +460,47 @@ add_entrypoint_object( libc.src.__support.threads.thread ) +add_entrypoint_object( + pthread_rwlockattr_destroy + SRCS + pthread_rwlockattr_destroy.cpp + HDRS + pthread_rwlockattr_destroy.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_rwlockattr_getpshared + SRCS + pthread_rwlockattr_getpshared.cpp + HDRS + pthread_rwlockattr_getpshared.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_rwlockattr_init + SRCS + pthread_rwlockattr_init.cpp + HDRS + pthread_rwlockattr_init.h + DEPENDS + libc.include.pthread +) + +add_entrypoint_object( + pthread_rwlockattr_setpshared + SRCS + pthread_rwlockattr_setpshared.cpp + HDRS + pthread_rwlockattr_setpshared.h + DEPENDS + libc.include.pthread + libc.include.errno +) + add_entrypoint_object( pthread_once SRCS diff --git a/libc/src/pthread/pthread_rwlockattr_destroy.cpp b/libc/src/pthread/pthread_rwlockattr_destroy.cpp new file mode 100644 index 000000000000..e3ca75112f0e --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_destroy.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of the pthread_rwlockattr_destroy ------------------===// +// +// 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 "pthread_rwlockattr_destroy.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_destroy, + (pthread_rwlockattr_t * attr [[gnu::unused]])) { + // Initializing a pthread_rwlockattr_t acquires no resources, so this is a + // no-op. + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_destroy.h b/libc/src/pthread/pthread_rwlockattr_destroy.h new file mode 100644 index 000000000000..5904d6b00418 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_destroy.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_destroy ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_DESTROY_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_DESTROY_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_DESTROY_H diff --git a/libc/src/pthread/pthread_rwlockattr_getpshared.cpp b/libc/src/pthread/pthread_rwlockattr_getpshared.cpp new file mode 100644 index 000000000000..0dad230a2bde --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_getpshared.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of the pthread_rwlockattr_getpshared ---------------===// +// +// 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 "pthread_rwlockattr_getpshared.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_getpshared, + (const pthread_rwlockattr_t *attr, int *pshared)) { + *pshared = attr->pshared; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_getpshared.h b/libc/src/pthread/pthread_rwlockattr_getpshared.h new file mode 100644 index 000000000000..64843e59aae6 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_getpshared.h @@ -0,0 +1,21 @@ +//===-- Implementation header for pthread_rwlockattr_getpshared -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETPSHARED_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETPSHARED_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, + int *pshared); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_GETPSHARED_H diff --git a/libc/src/pthread/pthread_rwlockattr_init.cpp b/libc/src/pthread/pthread_rwlockattr_init.cpp new file mode 100644 index 000000000000..7971f1714db4 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_init.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of the pthread_rwlockattr_init ---------------------===// +// +// 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 "pthread_rwlockattr_init.h" + +#include "src/__support/common.h" + +#include // pthread_rwlockattr_t, PTHREAD_PROCESS_PRIVATE + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_init, + (pthread_rwlockattr_t * attr)) { + attr->pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_init.h b/libc/src/pthread/pthread_rwlockattr_init.h new file mode 100644 index 000000000000..30ae499fb65d --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_init.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_init ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_INIT_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_INIT_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_init(pthread_rwlockattr_t *attr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_INIT_H diff --git a/libc/src/pthread/pthread_rwlockattr_setpshared.cpp b/libc/src/pthread/pthread_rwlockattr_setpshared.cpp new file mode 100644 index 000000000000..6bcba7c1b493 --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_setpshared.cpp @@ -0,0 +1,27 @@ +//===-- Implementation of the pthread_rwlockattr_setpshared ---------------===// +// +// 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 "pthread_rwlockattr_setpshared.h" + +#include "src/__support/common.h" + +#include // EINVAL +#include // pthread_rwlockattr_t, PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, pthread_rwlockattr_setpshared, + (pthread_rwlockattr_t * attr, int pshared)) { + if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE) + return EINVAL; + + attr->pshared = pshared; + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/pthread/pthread_rwlockattr_setpshared.h b/libc/src/pthread/pthread_rwlockattr_setpshared.h new file mode 100644 index 000000000000..393c07d1eecb --- /dev/null +++ b/libc/src/pthread/pthread_rwlockattr_setpshared.h @@ -0,0 +1,20 @@ +//===-- Implementation header for pthread_rwlockattr_setpshared -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETPSHARED_H +#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETPSHARED_H + +#include + +namespace LIBC_NAMESPACE { + +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_RWLOCKATTR_SETPSHARED_H diff --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt index 4d01b667f12c..ea75e65f57c9 100644 --- a/libc/test/src/pthread/CMakeLists.txt +++ b/libc/test/src/pthread/CMakeLists.txt @@ -56,4 +56,19 @@ add_libc_unittest( libc.src.pthread.pthread_condattr_init libc.src.pthread.pthread_condattr_setclock libc.src.pthread.pthread_condattr_setpshared - ) +) + +add_libc_unittest( + pthread_rwlockattr_test + SUITE + libc_pthread_unittests + SRCS + pthread_rwlockattr_test.cpp + DEPENDS + libc.include.errno + libc.include.pthread + libc.src.pthread.pthread_rwlockattr_destroy + libc.src.pthread.pthread_rwlockattr_getpshared + libc.src.pthread.pthread_rwlockattr_init + libc.src.pthread.pthread_rwlockattr_setpshared +) diff --git a/libc/test/src/pthread/pthread_rwlockattr_test.cpp b/libc/test/src/pthread/pthread_rwlockattr_test.cpp new file mode 100644 index 000000000000..6e5ae70df734 --- /dev/null +++ b/libc/test/src/pthread/pthread_rwlockattr_test.cpp @@ -0,0 +1,64 @@ +//===-- Unittests for pthread_rwlockattr_t --------------------------------===// +// +// 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 "include/llvm-libc-macros/generic-error-number-macros.h" // EINVAL +#include "src/pthread/pthread_rwlockattr_destroy.h" +#include "src/pthread/pthread_rwlockattr_getpshared.h" +#include "src/pthread/pthread_rwlockattr_init.h" +#include "src/pthread/pthread_rwlockattr_setpshared.h" +#include "test/UnitTest/Test.h" + +// TODO: https://github.com/llvm/llvm-project/issues/88997 +#include // PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED + +TEST(LlvmLibcPThreadRWLockAttrTest, InitAndDestroy) { + pthread_rwlockattr_t attr; + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} + +TEST(LlvmLibcPThreadRWLockAttrTest, GetDefaultValues) { + pthread_rwlockattr_t attr; + + // Invalid value. + int pshared = 42; + + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} + +TEST(LlvmLibcPThreadRWLockAttrTest, SetGoodValues) { + pthread_rwlockattr_t attr; + + // Invalid value. + int pshared = 42; + + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared( + &attr, PTHREAD_PROCESS_SHARED), + 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_SHARED); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} + +TEST(LlvmLibcPThreadRWLockAttrTest, SetBadValues) { + pthread_rwlockattr_t attr; + + // Invalid value. + int pshared = 42; + + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_init(&attr), 0); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_setpshared(&attr, pshared), + EINVAL); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_getpshared(&attr, &pshared), 0); + ASSERT_EQ(pshared, PTHREAD_PROCESS_PRIVATE); + ASSERT_EQ(LIBC_NAMESPACE::pthread_rwlockattr_destroy(&attr), 0); +} -- GitLab From 6b1b4c1c54d4276409c336eaf6d47b3bc04035c3 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 22 Apr 2024 12:04:15 -0700 Subject: [PATCH 212/357] [RISCV][clang] Don't enable -mrelax-all for -O0 on RISC-V (#88538) -O0 implies -mrelax-all as an assembler compile time optimization. -mrelax-all allows the assembler to complete layout in 2 passes instead of doing iterative branch relaxation. Jump offsets larger than +/-1MiB require an indirect jump on RISC-V. This can't be done by the assembler, so we use a branch relaxation MIR pass and use register scavenging to find a free register. The conditional branch offsets for RISC-V are also somewhat small so we support MC layer branch relaxation to make life easier for assembly programmers. This may also cover up bugs in our function size estimation in MachineIR. Enabling -mrelax-all causes the MC layer relaxation to agressively relax branches. This increases code size and can create cases where we need an indirect jump, but we can't create one. This leads to linker failures. The easiest way to avoid this is to not default to -mrelax-all for -O0 and sacrifice the compile time optimization. That's what this patch does. Fixes #87127 --- clang/lib/Driver/ToolChains/Clang.cpp | 10 ++++++++++ clang/test/Driver/integrated-as.c | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f8a81ee8ab56..5894a48e0e37 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -847,6 +847,16 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_O_Group)) RelaxDefault = A->getOption().matches(options::OPT_O0); + // RISC-V requires an indirect jump for offsets larger than 1MiB. This cannot + // be done by assembler branch relaxation as it needs a free temporary + // register. Because of this, branch relaxation is handled by a MachineIR + // pass before the assembler. Forcing assembler branch relaxation for -O0 + // makes the MachineIR branch relaxation inaccurate and it will miss cases + // where an indirect branch is necessary. To avoid this issue we are + // sacrificing the compile time improvement of using -mrelax-all for -O0. + if (C.getDefaultToolChain().getTriple().isRISCV()) + RelaxDefault = false; + if (RelaxDefault) { RelaxDefault = false; for (const auto &Act : C.getActions()) { diff --git a/clang/test/Driver/integrated-as.c b/clang/test/Driver/integrated-as.c index d7658fdfd633..e78fde873cf4 100644 --- a/clang/test/Driver/integrated-as.c +++ b/clang/test/Driver/integrated-as.c @@ -1,10 +1,16 @@ // XFAIL: target={{.*}}-aix{{.*}} -// RUN: %clang -### -c -save-temps -integrated-as %s 2>&1 | FileCheck %s +// RUN: %clang -### -c -save-temps -integrated-as --target=x86_64 %s 2>&1 | FileCheck %s // CHECK: cc1as // CHECK: -mrelax-all +// RISC-V does not enable -mrelax-all +// RUN: %clang -### -c -save-temps -integrated-as --target=riscv64 %s 2>&1 | FileCheck %s -check-prefix=RISCV-RELAX + +// RISCV-RELAX: cc1as +// RISCV-RELAX-NOT: -mrelax-all + // RUN: %clang -### -fintegrated-as -c -save-temps %s 2>&1 | FileCheck %s -check-prefix FIAS // FIAS: cc1as -- GitLab From a6f1b3a4c79209b01733bc1857c87b2abe0b4ecf Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 22 Apr 2024 14:10:12 -0500 Subject: [PATCH 213/357] [Offload] Fix per-target install directory (#89645) Summary: The move from `openmp` to `offload` did not preserve the per-target runtime directory installation. This is important because this per-target directory is always included first and is likely the de-facto way to handle these going forward. Without this installation, old installations of the library will be linked against first. --- offload/CMakeLists.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt index b23ffdcbd5aa..abc8baa0805f 100644 --- a/offload/CMakeLists.txt +++ b/offload/CMakeLists.txt @@ -39,8 +39,21 @@ if (OPENMP_ENABLE_LIBOMPTARGET) endif() endif() -# TODO: Leftover from the move, could probably be just LLVM_LIBDIR_SUFFIX everywhere. -set(OFFLOAD_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}") +if(OPENMP_STANDALONE_BUILD) + set(OFFLOAD_LIBDIR_SUFFIX "" CACHE STRING + "Suffix of lib installation directory, e.g. 64 => lib64") + set(OFFLOAD_INSTALL_LIBDIR "lib${OFFLOAD_LIBDIR_SUFFIX}" CACHE STRING + "Path where built offload libraries should be installed.") +else() + # When building in tree we install the runtime according to the LLVM settings. + if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + set(OFFLOAD_INSTALL_LIBDIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING + "Path where built offload libraries should be installed.") + else() + set(OFFLOAD_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}" CACHE STRING + "Path where built offload libraries should be installed.") + endif() +endif() set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) -- GitLab From 89c95effe82c09b9a42408f4823409331f8fa266 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 22 Apr 2024 12:35:04 -0700 Subject: [PATCH 214/357] [llvm-readobj] Remove --raw-relr https://reviews.llvm.org/D47919 dumped RELR relocations as `R_*_RELATIVE` and added --raw-relr (not in GNU) for testing purposes (more readable than `llvm-readelf -x .relr.dyn`). The option is obsolete after `llvm-readelf -r` output gets improved (#89162). Since --raw-relr never seems to get more adoption. Let's remove it to avoid some complexity. Pull Request: https://github.com/llvm/llvm-project/pull/89426 --- llvm/docs/CommandGuide/llvm-readelf.rst | 4 -- llvm/docs/CommandGuide/llvm-readobj.rst | 4 -- llvm/docs/ReleaseNotes.rst | 4 ++ .../tools/llvm-readobj/ELF/relr-relocs.test | 49 +------------ llvm/tools/llvm-readobj/ELFDumper.cpp | 68 ++++--------------- llvm/tools/llvm-readobj/Opts.td | 1 - llvm/tools/llvm-readobj/llvm-readobj.cpp | 2 - llvm/tools/llvm-readobj/llvm-readobj.h | 1 - 8 files changed, 21 insertions(+), 112 deletions(-) diff --git a/llvm/docs/CommandGuide/llvm-readelf.rst b/llvm/docs/CommandGuide/llvm-readelf.rst index 675628fdda45..284c3aa470a6 100644 --- a/llvm/docs/CommandGuide/llvm-readelf.rst +++ b/llvm/docs/CommandGuide/llvm-readelf.rst @@ -152,10 +152,6 @@ OPTIONS Display the program headers. -.. option:: --raw-relr - - Do not decode relocations in RELR relocation sections when displaying them. - .. option:: --relocations, --relocs, -r Display the relocation entries in the file. diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst index ca7fb253f00a..8bd29eafbbfc 100644 --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -255,10 +255,6 @@ The following options are implemented only for the ELF file format. Display the program headers. -.. option:: --raw-relr - - Do not decode relocations in RELR relocation sections when displaying them. - .. option:: --section-mapping Display the section to segment mapping. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 76ef6ceb9407..580dc512d969 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -198,6 +198,10 @@ Changes to the LLVM tools documentation for SPGO `_. +* llvm-readelf's ``-r`` output for RELR has been improved. + (`#89162 `_) + ``--raw-relr`` has been removed. + Changes to LLDB --------------------------------- diff --git a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test index 9b59f991c051..c22239900bcf 100644 --- a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test +++ b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test @@ -1,16 +1,6 @@ ## This is a test to test how SHT_RELR sections are dumped. # RUN: yaml2obj --docnum=1 %s -o %t1 -# RUN: llvm-readobj --relocations --raw-relr %t1 \ -# RUN: | FileCheck --check-prefix=RAW-LLVM1 %s -# RAW-LLVM1: Section (1) .relr.dyn { -# RAW-LLVM1-NEXT: 0x10D60 -# RAW-LLVM1-NEXT: 0x103 -# RAW-LLVM1-NEXT: 0x20000 -# RAW-LLVM1-NEXT: 0xF0501 -# RAW-LLVM1-NEXT: 0xA700550400009 -# RAW-LLVM1-NEXT: } - # RUN: llvm-readobj --relocations %t1 | \ # RUN: FileCheck --match-full-lines --check-prefix=LLVM1 %s @@ -38,15 +28,6 @@ # LLVM1-NEXT: 0x20390 R_X86_64_RELATIVE - # LLVM1-NEXT: } -# RUN: llvm-readelf --relocations --raw-relr %t1 \ -# RUN: | FileCheck --check-prefix=RAW-GNU1 %s -# RAW-GNU1: Relocation section '.relr.dyn' at offset 0x40 contains 5 entries: -# RAW-GNU1: 0000000000010d60 -# RAW-GNU1-NEXT: 0000000000000103 -# RAW-GNU1-NEXT: 0000000000020000 -# RAW-GNU1-NEXT: 00000000000f0501 -# RAW-GNU1-NEXT: 000a700550400009 - # RUN: llvm-readelf --relocations %t1 | FileCheck --check-prefix=GNU1 --match-full-lines --strict-whitespace %s # GNU1:Relocation section '.relr.dyn' at offset 0x40 contains 21 entries: # GNU1-NEXT:Index: Entry Address Symbolic Address @@ -107,16 +88,6 @@ Symbols: Value: 0x20210 # RUN: yaml2obj --docnum=2 %s -o %t2 -# RUN: llvm-readobj --relocations --raw-relr %t2 | \ -# RUN: FileCheck --check-prefix=RAW-LLVM2 %s -# RAW-LLVM2: Section (1) .relr.dyn { -# RAW-LLVM2-NEXT: 0x10D60 -# RAW-LLVM2-NEXT: 0x103 -# RAW-LLVM2-NEXT: 0x20000 -# RAW-LLVM2-NEXT: 0xF0501 -# RAW-LLVM2-NEXT: 0x50400009 -# RAW-LLVM2-NEXT: } - # RUN: llvm-readobj --relocations %t2 | \ # RUN: FileCheck --match-full-lines --check-prefix=LLVM2 %s @@ -137,15 +108,6 @@ Symbols: # LLVM2-NEXT: 0x200F4 R_386_RELATIVE - # LLVM2-NEXT: } -# RUN: llvm-readelf --relocations --raw-relr %t2 | \ -# RUN: FileCheck --check-prefix=RAW-GNU2 %s -# RAW-GNU2: Relocation section '.relr.dyn' at offset 0x34 contains 5 entries: -# RAW-GNU2: 00010d60 -# RAW-GNU2-NEXT: 00000103 -# RAW-GNU2-NEXT: 00020000 -# RAW-GNU2-NEXT: 000f0501 -# RAW-GNU2-NEXT: 50400009 - # RUN: llvm-readelf --relocations %t2 | FileCheck --check-prefix=GNU2 --match-full-lines --strict-whitespace %s # GNU2:Relocation section '.relr.dyn' at offset 0x34 contains 14 entries: # GNU2-NEXT:Index: Entry Address Symbolic Address @@ -232,21 +194,14 @@ Symbols: ## only relative relocations and do not have an associated symbol table, like other ## relocation sections. -## Case A: check we do not report warnings when the sh_link field is set to an arbitrary value -## and the --relocations option is requested. +## Check we do not report warnings when the sh_link field is set to an arbitrary value +## and the --relocations option is requested. # RUN: yaml2obj --docnum=2 -DLINK=0xff %s -o %t2.has.link # RUN: llvm-readobj --relocations %t2.has.link 2>&1 | \ # RUN: FileCheck -DFILE=%t2.has.link --check-prefix=LLVM2 %s --implicit-check-not=warning: # RUN: llvm-readelf --relocations %t2.has.link 2>&1 | \ # RUN: FileCheck -DFILE=%t2.has.link --check-prefix=GNU2 %s --implicit-check-not=warning: -## Case B: check we do not report warnings when the sh_link field is set to an arbitrary value -## and --relocations and --raw-relr options are requested. -# RUN: llvm-readobj --relocations --raw-relr %t2.has.link | \ -# RUN: FileCheck -DFILE=%t2.has.link --check-prefix=RAW-LLVM2 %s -# RUN: llvm-readelf --relocations --raw-relr %t2.has.link 2>&1 | \ -# RUN: FileCheck -DFILE=%t2.has.link --check-prefix=RAW-GNU2 %s - ## .symtab is invalid. Check we report a warning and print entries without symbolization. # RUN: yaml2obj --docnum=3 -DENTSIZE=1 %s -o %t3.err1 # RUN: llvm-readelf -r %t3.err1 2>&1 | FileCheck -DFILE=%t3.err1 --check-prefixes=GNU3,GNU3-ERR1 --match-full-lines %s diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index f145653ac743..a752cc401529 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -285,7 +285,6 @@ protected: virtual void printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) = 0; - virtual void printRelrReloc(const Elf_Relr &R) = 0; virtual void printDynamicRelocHeader(unsigned Type, StringRef Name, const DynRegionInfo &Reg) {} void printReloc(const Relocation &R, unsigned RelIndex, @@ -294,11 +293,10 @@ protected: void printDynamicRelocationsHelper(); void printRelocationsHelper(const Elf_Shdr &Sec); void forEachRelocationDo( - const Elf_Shdr &Sec, bool RawRelr, + const Elf_Shdr &Sec, llvm::function_ref &, unsigned, const Elf_Shdr &, const Elf_Shdr *)> - RelRelaFn, - llvm::function_ref RelrFn); + RelRelaFn); virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset, bool NonVisibilityBitsUsed, @@ -669,7 +667,6 @@ private: DataRegion ShndxTable, StringRef StrTable, uint32_t Bucket); void printRelr(const Elf_Shdr &Sec); - void printRelrReloc(const Elf_Relr &R) override; void printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) override; void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, @@ -734,7 +731,6 @@ public: bool IsGnu) const override; private: - void printRelrReloc(const Elf_Relr &R) override; void printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) override; @@ -3800,11 +3796,6 @@ template void GNUELFDumper::printGroupSections() { OS << "There are no section groups in this file.\n"; } -template -void GNUELFDumper::printRelrReloc(const Elf_Relr &R) { - OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) << "\n"; -} - template void GNUELFDumper::printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) { @@ -3851,22 +3842,11 @@ template static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType, const typename ELFT::Ehdr &EHeader) { bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; - bool IsRelr = - SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR || - (EHeader.e_machine == EM_AARCH64 && SType == ELF::SHT_AARCH64_AUTH_RELR); - if (ELFT::Is64Bits) - OS << " "; - else - OS << " "; - if (IsRelr && opts::RawRelr) - OS << "Data "; - else - OS << "Offset"; if (ELFT::Is64Bits) - OS << " Info Type" - << " Symbol's Value Symbol's Name"; + OS << " Offset Info Type Symbol's " + "Value Symbol's Name"; else - OS << " Info Type Sym. Value Symbol's Name"; + OS << " Offset Info Type Sym. Value Symbol's Name"; if (IsRela) OS << " + Addend"; OS << "\n"; @@ -3894,10 +3874,10 @@ static bool isRelocationSec(const typename ELFT::Shdr &Sec, template void GNUELFDumper::printRelocations() { auto PrintAsRelr = [&](const Elf_Shdr &Sec) { - return !opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || - Sec.sh_type == ELF::SHT_ANDROID_RELR || - (this->Obj.getHeader().e_machine == EM_AARCH64 && - Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)); + return Sec.sh_type == ELF::SHT_RELR || + Sec.sh_type == ELF::SHT_ANDROID_RELR || + (this->Obj.getHeader().e_machine == EM_AARCH64 && + Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR); }; auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected { // Android's packed relocation section needs to be unpacked first @@ -4902,10 +4882,8 @@ void ELFDumper::printDynamicReloc(const Relocation &R) { template void ELFDumper::printRelocationsHelper(const Elf_Shdr &Sec) { this->forEachRelocationDo( - Sec, opts::RawRelr, - [&](const Relocation &R, unsigned Ndx, const Elf_Shdr &Sec, - const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); }, - [&](const Elf_Relr &R) { printRelrReloc(R); }); + Sec, [&](const Relocation &R, unsigned Ndx, const Elf_Shdr &Sec, + const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); }); } template void ELFDumper::printDynamicRelocationsHelper() { @@ -6371,11 +6349,10 @@ void ELFDumper::printDependentLibsHelper( template void ELFDumper::forEachRelocationDo( - const Elf_Shdr &Sec, bool RawRelr, + const Elf_Shdr &Sec, llvm::function_ref &, unsigned, const Elf_Shdr &, const Elf_Shdr *)> - RelRelaFn, - llvm::function_ref RelrFn) { + RelRelaFn) { auto Warn = [&](Error &&E, const Twine &Prefix = "unable to read relocations from") { this->reportUniqueWarning(Prefix + " " + describe(Sec) + ": " + @@ -6427,11 +6404,6 @@ void ELFDumper::forEachRelocationDo( Warn(RangeOrErr.takeError()); break; } - if (RawRelr) { - for (const Elf_Relr &R : *RangeOrErr) - RelrFn(R); - break; - } for (const Elf_Rel &R : Obj.decode_relrs(*RangeOrErr)) RelRelaFn(Relocation(R, IsMips64EL), RelNdx++, Sec, @@ -6741,9 +6713,8 @@ void ELFDumper::printRelocatableStackSizes( DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr)); forEachRelocationDo( - *RelocSec, /*RawRelr=*/false, - [&](const Relocation &R, unsigned Ndx, const Elf_Shdr &Sec, - const Elf_Shdr *SymTab) { + *RelocSec, [&](const Relocation &R, unsigned Ndx, + const Elf_Shdr &Sec, const Elf_Shdr *SymTab) { if (!IsSupportedFn || !IsSupportedFn(R.Type)) { reportUniqueWarning( describe(*RelocSec) + @@ -6754,10 +6725,6 @@ void ELFDumper::printRelocatableStackSizes( this->printStackSize(R, *RelocSec, Ndx, SymTab, FunctionSec, *StackSizesELFSec, Resolver, Data); - }, - [](const Elf_Relr &) { - llvm_unreachable("can't get here, because we only support " - "SHT_REL/SHT_RELA sections"); }); } } @@ -7147,11 +7114,6 @@ template void LLVMELFDumper::printRelocations() { } } -template -void LLVMELFDumper::printRelrReloc(const Elf_Relr &R) { - W.startLine() << W.hex(R) << "\n"; -} - template void LLVMELFDumper::printExpandedRelRelaReloc(const Relocation &R, StringRef SymbolName, diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index 1e9cde6b2e87..7d574d875d22 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -62,7 +62,6 @@ def memtag : FF<"memtag", "Display memory tagging metadata (modes, Android notes def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group; def notes : FF<"notes", "Display notes">, Group; def program_headers : FF<"program-headers", "Display program headers">, Group; -def raw_relr : FF<"raw-relr", "Do not decode relocations in SHT_RELR section, display raw contents">, Group; def version_info : FF<"version-info", "Display version sections">, Group; // Mach-O specific options. diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index a0b576566016..9ac324cc672f 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -134,7 +134,6 @@ static bool Memtag; static bool NeededLibraries; static bool Notes; static bool ProgramHeaders; -bool RawRelr; static bool SectionGroups; static bool VersionInfo; @@ -273,7 +272,6 @@ static void parseOptions(const opt::InputArgList &Args) { opts::Notes = Args.hasArg(OPT_notes); opts::PrettyPrint = Args.hasArg(OPT_pretty_print); opts::ProgramHeaders = Args.hasArg(OPT_program_headers); - opts::RawRelr = Args.hasArg(OPT_raw_relr); opts::SectionGroups = Args.hasArg(OPT_section_groups); if (Arg *A = Args.getLastArg(OPT_sort_symbols_EQ)) { std::string SortKeysString = A->getValue(); diff --git a/llvm/tools/llvm-readobj/llvm-readobj.h b/llvm/tools/llvm-readobj/llvm-readobj.h index 532e43d4e16b..e4ee2c1396b2 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.h +++ b/llvm/tools/llvm-readobj/llvm-readobj.h @@ -38,7 +38,6 @@ extern bool SectionRelocations; extern bool SectionSymbols; extern bool SectionData; extern bool ExpandRelocs; -extern bool RawRelr; extern bool CodeViewSubsectionBytes; extern bool Demangle; enum OutputStyleTy { LLVM, GNU, JSON, UNKNOWN }; -- GitLab From 40137ff0d81be80e4900c17c57b1f66c53ddf2f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Apr 2024 14:41:11 -0500 Subject: [PATCH 215/357] [Frontend][OpenMP] Refactor getLeafConstructs, add getCompoundConstruct (#87247) Emit a special leaf construct table in DirectiveEmitter.cpp, which will allow both decomposition of a construct into leafs, and composition of constituent constructs into a single compound construct (if possible). The function `getLeafConstructs` is no longer auto-generated, but implemented in OMP.cpp. The table contains a row for each directive, and each row has the following format `dir_id, num_leafs, leaf1, leaf2, ..., leafN, -1, ...` The rows are sorted lexicographically with respect to the leaf constructs. This allows a binary search for the row corresponding to the given list of leafs. There is an auxiliary table that for each directive contains the index of the row corresponding to that directive. Looking up leaf constructs for a directive `dir_id` is of constant time, and and consists of two lookups: `LeafTable[Auxiliary[dir_id]]`. Finding a compound directive given the set of leafs is of time O(logn), and is roughly represented by `row = binary_search(LeafTable); return row[0]`. The functions `getLeafConstructs` and `getCompoundConstruct` use these lookup methods internally. --- llvm/include/llvm/Frontend/OpenMP/OMP.h | 7 + llvm/lib/Frontend/OpenMP/OMP.cpp | 70 +++++- llvm/test/TableGen/directive1.td | 21 +- llvm/test/TableGen/directive2.td | 21 +- llvm/unittests/Frontend/CMakeLists.txt | 1 + llvm/unittests/Frontend/OpenMPComposeTest.cpp | 41 ++++ llvm/utils/TableGen/DirectiveEmitter.cpp | 226 ++++++++++++------ 7 files changed, 301 insertions(+), 86 deletions(-) create mode 100644 llvm/unittests/Frontend/OpenMPComposeTest.cpp diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h index a85cd9d344c6..4ed47f15dfe5 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h @@ -15,4 +15,11 @@ #include "llvm/Frontend/OpenMP/OMP.h.inc" +#include "llvm/ADT/ArrayRef.h" + +namespace llvm::omp { +ArrayRef getLeafConstructs(Directive D); +Directive getCompoundConstruct(ArrayRef Parts); +} // namespace llvm::omp + #endif // LLVM_FRONTEND_OPENMP_OMP_H diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp index 4f2f95392648..e958bced3a42 100644 --- a/llvm/lib/Frontend/OpenMP/OMP.cpp +++ b/llvm/lib/Frontend/OpenMP/OMP.cpp @@ -8,12 +8,80 @@ #include "llvm/Frontend/OpenMP/OMP.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include +#include +#include + using namespace llvm; -using namespace omp; +using namespace llvm::omp; #define GEN_DIRECTIVES_IMPL #include "llvm/Frontend/OpenMP/OMP.inc" + +namespace llvm::omp { +ArrayRef getLeafConstructs(Directive D) { + auto Idx = static_cast(D); + if (Idx >= Directive_enumSize) + std::nullopt; + const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]]; + return ArrayRef(&Row[2], static_cast(Row[1])); +} + +Directive getCompoundConstruct(ArrayRef Parts) { + if (Parts.empty()) + return OMPD_unknown; + + // Parts don't have to be leafs, so expand them into leafs first. + // Store the expanded leafs in the same format as rows in the leaf + // table (generated by tablegen). + SmallVector RawLeafs(2); + for (Directive P : Parts) { + ArrayRef Ls = getLeafConstructs(P); + if (!Ls.empty()) + RawLeafs.append(Ls.begin(), Ls.end()); + else + RawLeafs.push_back(P); + } + + // RawLeafs will be used as key in the binary search. The search doesn't + // guarantee that the exact same entry will be found (since RawLeafs may + // not correspond to any compound directive). Because of that, we will + // need to compare the search result with the given set of leafs. + // Also, if there is only one leaf in the list, it corresponds to itself, + // no search is necessary. + auto GivenLeafs{ArrayRef(RawLeafs).drop_front(2)}; + if (GivenLeafs.size() == 1) + return GivenLeafs.front(); + RawLeafs[1] = static_cast(GivenLeafs.size()); + + auto Iter = std::lower_bound( + LeafConstructTable, LeafConstructTableEndDirective, + static_cast>(RawLeafs.data()), + [](const llvm::omp::Directive *RowA, const llvm::omp::Directive *RowB) { + const auto *BeginA = &RowA[2]; + const auto *EndA = BeginA + static_cast(RowA[1]); + const auto *BeginB = &RowB[2]; + const auto *EndB = BeginB + static_cast(RowB[1]); + if (BeginA == EndA && BeginB == EndB) + return static_cast(RowA[0]) < static_cast(RowB[0]); + return std::lexicographical_compare(BeginA, EndA, BeginB, EndB); + }); + + if (Iter == std::end(LeafConstructTable)) + return OMPD_unknown; + + // Verify that we got a match. + Directive Found = (*Iter)[0]; + ArrayRef FoundLeafs = getLeafConstructs(Found); + if (FoundLeafs == GivenLeafs) + return Found; + return OMPD_unknown; +} +} // namespace llvm::omp diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td index 3184f625ead9..526dcb3c3bf0 100644 --- a/llvm/test/TableGen/directive1.td +++ b/llvm/test/TableGen/directive1.td @@ -52,6 +52,7 @@ def TDL_DirA : Directive<"dira"> { // CHECK-EMPTY: // CHECK-NEXT: #include "llvm/ADT/ArrayRef.h" // CHECK-NEXT: #include "llvm/ADT/BitmaskEnum.h" +// CHECK-NEXT: #include // CHECK-EMPTY: // CHECK-NEXT: namespace llvm { // CHECK-NEXT: class StringRef; @@ -112,7 +113,7 @@ def TDL_DirA : Directive<"dira"> { // CHECK-NEXT: /// Return true if \p C is a valid clause for \p D in version \p Version. // CHECK-NEXT: bool isAllowedClauseForDirective(Directive D, Clause C, unsigned Version); // CHECK-EMPTY: -// CHECK-NEXT: llvm::ArrayRef getLeafConstructs(Directive D); +// CHECK-NEXT: constexpr std::size_t getMaxLeafCount() { return 0; } // CHECK-NEXT: Association getDirectiveAssociation(Directive D); // CHECK-NEXT: AKind getAKind(StringRef); // CHECK-NEXT: llvm::StringRef getTdlAKindName(AKind); @@ -359,13 +360,6 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind"); // IMPL-NEXT: } // IMPL-EMPTY: -// IMPL-NEXT: llvm::ArrayRef llvm::tdl::getLeafConstructs(llvm::tdl::Directive Dir) { -// IMPL-NEXT: switch (Dir) { -// IMPL-NEXT: default: -// IMPL-NEXT: return ArrayRef{}; -// IMPL-NEXT: } // switch (Dir) -// IMPL-NEXT: } -// IMPL-EMPTY: // IMPL-NEXT: llvm::tdl::Association llvm::tdl::getDirectiveAssociation(llvm::tdl::Directive Dir) { // IMPL-NEXT: switch (Dir) { // IMPL-NEXT: case llvm::tdl::Directive::TDLD_dira: @@ -374,4 +368,15 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: llvm_unreachable("Unexpected directive"); // IMPL-NEXT: } // IMPL-EMPTY: +// IMPL-NEXT: static_assert(sizeof(llvm::tdl::Directive) == sizeof(int)); +// IMPL-NEXT: {{.*}} static const llvm::tdl::Directive LeafConstructTable[][2] = { +// IMPL-NEXT: llvm::tdl::TDLD_dira, static_cast(0), +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: {{.*}} static auto LeafConstructTableEndDirective = LeafConstructTable + 1; +// IMPL-EMPTY: +// IMPL-NEXT: {{.*}} static const int LeafConstructTableOrdering[] = { +// IMPL-NEXT: 0, +// IMPL-NEXT: }; +// IMPL-EMPTY: // IMPL-NEXT: #endif // GEN_DIRECTIVES_IMPL diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td index d6fa4835c8df..9df8a06d3e51 100644 --- a/llvm/test/TableGen/directive2.td +++ b/llvm/test/TableGen/directive2.td @@ -45,6 +45,7 @@ def TDL_DirA : Directive<"dira"> { // CHECK-NEXT: #define LLVM_Tdl_INC // CHECK-EMPTY: // CHECK-NEXT: #include "llvm/ADT/ArrayRef.h" +// CHECK-NEXT: #include // CHECK-EMPTY: // CHECK-NEXT: namespace llvm { // CHECK-NEXT: class StringRef; @@ -88,7 +89,7 @@ def TDL_DirA : Directive<"dira"> { // CHECK-NEXT: /// Return true if \p C is a valid clause for \p D in version \p Version. // CHECK-NEXT: bool isAllowedClauseForDirective(Directive D, Clause C, unsigned Version); // CHECK-EMPTY: -// CHECK-NEXT: llvm::ArrayRef getLeafConstructs(Directive D); +// CHECK-NEXT: constexpr std::size_t getMaxLeafCount() { return 0; } // CHECK-NEXT: Association getDirectiveAssociation(Directive D); // CHECK-NEXT: } // namespace tdl // CHECK-NEXT: } // namespace llvm @@ -290,13 +291,6 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind"); // IMPL-NEXT: } // IMPL-EMPTY: -// IMPL-NEXT: llvm::ArrayRef llvm::tdl::getLeafConstructs(llvm::tdl::Directive Dir) { -// IMPL-NEXT: switch (Dir) { -// IMPL-NEXT: default: -// IMPL-NEXT: return ArrayRef{}; -// IMPL-NEXT: } // switch (Dir) -// IMPL-NEXT: } -// IMPL-EMPTY: // IMPL-NEXT: llvm::tdl::Association llvm::tdl::getDirectiveAssociation(llvm::tdl::Directive Dir) { // IMPL-NEXT: switch (Dir) { // IMPL-NEXT: case llvm::tdl::Directive::TDLD_dira: @@ -305,4 +299,15 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: llvm_unreachable("Unexpected directive"); // IMPL-NEXT: } // IMPL-EMPTY: +// IMPL-NEXT: static_assert(sizeof(llvm::tdl::Directive) == sizeof(int)); +// IMPL-NEXT: {{.*}} static const llvm::tdl::Directive LeafConstructTable[][2] = { +// IMPL-NEXT: llvm::tdl::TDLD_dira, static_cast(0), +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: {{.*}} static auto LeafConstructTableEndDirective = LeafConstructTable + 1; +// IMPL-EMPTY: +// IMPL-NEXT: {{.*}} static const int LeafConstructTableOrdering[] = { +// IMPL-NEXT: 0, +// IMPL-NEXT: }; +// IMPL-EMPTY: // IMPL-NEXT: #endif // GEN_DIRECTIVES_IMPL diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt index c6f60142d627..ddb6a16cbb98 100644 --- a/llvm/unittests/Frontend/CMakeLists.txt +++ b/llvm/unittests/Frontend/CMakeLists.txt @@ -14,6 +14,7 @@ add_llvm_unittest(LLVMFrontendTests OpenMPContextTest.cpp OpenMPIRBuilderTest.cpp OpenMPParsingTest.cpp + OpenMPComposeTest.cpp DEPENDS acc_gen diff --git a/llvm/unittests/Frontend/OpenMPComposeTest.cpp b/llvm/unittests/Frontend/OpenMPComposeTest.cpp new file mode 100644 index 000000000000..c5fbe6ec6adf --- /dev/null +++ b/llvm/unittests/Frontend/OpenMPComposeTest.cpp @@ -0,0 +1,41 @@ +//===- llvm/unittests/Frontend/OpenMPComposeTest.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 "llvm/ADT/ArrayRef.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::omp; + +TEST(Composition, GetLeafConstructs) { + ArrayRef L1 = getLeafConstructs(OMPD_loop); + ASSERT_EQ(L1, (ArrayRef{})); + ArrayRef L2 = getLeafConstructs(OMPD_parallel_for); + ASSERT_EQ(L2, (ArrayRef{OMPD_parallel, OMPD_for})); + ArrayRef L3 = getLeafConstructs(OMPD_parallel_for_simd); + ASSERT_EQ(L3, (ArrayRef{OMPD_parallel, OMPD_for, OMPD_simd})); +} + +TEST(Composition, GetCompoundConstruct) { + Directive C1 = + getCompoundConstruct({OMPD_target, OMPD_teams, OMPD_distribute}); + ASSERT_EQ(C1, OMPD_target_teams_distribute); + Directive C2 = getCompoundConstruct({OMPD_target}); + ASSERT_EQ(C2, OMPD_target); + Directive C3 = getCompoundConstruct({OMPD_target, OMPD_masked}); + ASSERT_EQ(C3, OMPD_unknown); + Directive C4 = getCompoundConstruct({OMPD_target, OMPD_teams_distribute}); + ASSERT_EQ(C4, OMPD_target_teams_distribute); + Directive C5 = getCompoundConstruct({}); + ASSERT_EQ(C5, OMPD_unknown); + Directive C6 = getCompoundConstruct({OMPD_parallel_for, OMPD_simd}); + ASSERT_EQ(C6, OMPD_parallel_for_simd); + Directive C7 = getCompoundConstruct({OMPD_do, OMPD_simd}); + ASSERT_EQ(C7, OMPD_do_simd); // Make sure it's not OMPD_end_do_simd +} diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp index e0edf1720f8a..69d9c5e8325a 100644 --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/TableGen/DirectiveEmitter.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSet.h" @@ -20,6 +22,9 @@ #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include +#include + using namespace llvm; namespace { @@ -39,7 +44,8 @@ private: }; } // namespace -// Generate enum class +// Generate enum class. Entries are emitted in the order in which they appear +// in the `Records` vector. static void GenerateEnumClass(const std::vector &Records, raw_ostream &OS, StringRef Enum, StringRef Prefix, const DirectiveLanguage &DirLang, @@ -175,6 +181,16 @@ bool DirectiveLanguage::HasValidityErrors() const { return HasDuplicateClausesInDirectives(getDirectives()); } +// Count the maximum number of leaf constituents per construct. +static size_t GetMaxLeafCount(const DirectiveLanguage &DirLang) { + size_t MaxCount = 0; + for (Record *R : DirLang.getDirectives()) { + size_t Count = Directive{R}.getLeafConstructs().size(); + MaxCount = std::max(MaxCount, Count); + } + return MaxCount; +} + // Generate the declaration section for the enumeration in the directive // language static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { @@ -189,6 +205,7 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { if (DirLang.hasEnableBitmaskEnumInNamespace()) OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n"; + OS << "#include \n"; // for size_t OS << "\n"; OS << "namespace llvm {\n"; OS << "class StringRef;\n"; @@ -244,7 +261,8 @@ static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { OS << "bool isAllowedClauseForDirective(Directive D, " << "Clause C, unsigned Version);\n"; OS << "\n"; - OS << "llvm::ArrayRef getLeafConstructs(Directive D);\n"; + OS << "constexpr std::size_t getMaxLeafCount() { return " + << GetMaxLeafCount(DirLang) << "; }\n"; OS << "Association getDirectiveAssociation(Directive D);\n"; if (EnumHelperFuncs.length() > 0) { OS << EnumHelperFuncs; @@ -396,6 +414,19 @@ GenerateCaseForVersionedClauses(const std::vector &Clauses, } } +static std::string GetDirectiveName(const DirectiveLanguage &DirLang, + const Record *Rec) { + Directive Dir{Rec}; + return (llvm::Twine("llvm::") + DirLang.getCppNamespace() + + "::" + DirLang.getDirectivePrefix() + Dir.getFormattedName()) + .str(); +} + +static std::string GetDirectiveType(const DirectiveLanguage &DirLang) { + return (llvm::Twine("llvm::") + DirLang.getCppNamespace() + "::Directive") + .str(); +} + // Generate the isAllowedClauseForDirective function implementation. static void GenerateIsAllowedClause(const DirectiveLanguage &DirLang, raw_ostream &OS) { @@ -450,77 +481,134 @@ static void GenerateIsAllowedClause(const DirectiveLanguage &DirLang, OS << "}\n"; // End of function isAllowedClauseForDirective } -// Generate the getLeafConstructs function implementation. -static void GenerateGetLeafConstructs(const DirectiveLanguage &DirLang, - raw_ostream &OS) { - auto getQualifiedName = [&](StringRef Formatted) -> std::string { - return (llvm::Twine("llvm::") + DirLang.getCppNamespace() + - "::Directive::" + DirLang.getDirectivePrefix() + Formatted) - .str(); - }; - - // For each list of leaves, generate a static local object, then - // return a reference to that object for a given directive, e.g. +static void EmitLeafTable(const DirectiveLanguage &DirLang, raw_ostream &OS, + StringRef TableName) { + // The leaf constructs are emitted in a form of a 2D table, where each + // row corresponds to a directive (and there is a row for each directive). // - // static ListTy leafConstructs_A_B = { A, B }; - // static ListTy leafConstructs_C_D_E = { C, D, E }; - // switch (Dir) { - // case A_B: - // return leafConstructs_A_B; - // case C_D_E: - // return leafConstructs_C_D_E; - // } - - // Map from a record that defines a directive to the name of the - // local object with the list of its leaves. - DenseMap ListNames; - - std::string DirectiveTypeName = - std::string("llvm::") + DirLang.getCppNamespace().str() + "::Directive"; - - OS << '\n'; - - // ArrayRef<...> llvm::::GetLeafConstructs(llvm::::Directive Dir) - OS << "llvm::ArrayRef<" << DirectiveTypeName - << "> llvm::" << DirLang.getCppNamespace() << "::getLeafConstructs(" - << DirectiveTypeName << " Dir) "; - OS << "{\n"; + // Each row consists of + // - the id of the directive itself, + // - number of leaf constructs that will follow (0 for leafs), + // - ids of the leaf constructs (none if the directive is itself a leaf). + // The total number of these entries is at most MaxLeafCount+2. If this + // number is less than that, it is padded to occupy exactly MaxLeafCount+2 + // entries in memory. + // + // The rows are stored in the table in the lexicographical order. This + // is intended to enable binary search when mapping a sequence of leafs + // back to the compound directive. + // The consequence of that is that in order to find a row corresponding + // to the given directive, we'd need to scan the first element of each + // row. To avoid this, an auxiliary ordering table is created, such that + // row for Dir_A = table[auxiliary[Dir_A]]. + + std::vector Directives = DirLang.getDirectives(); + DenseMap DirId; // Record * -> llvm::omp::Directive + + for (auto [Idx, Rec] : llvm::enumerate(Directives)) + DirId.insert(std::make_pair(Rec, Idx)); + + using LeafList = std::vector; + int MaxLeafCount = GetMaxLeafCount(DirLang); + + // The initial leaf table, rows order is same as directive order. + std::vector LeafTable(Directives.size()); + for (auto [Idx, Rec] : llvm::enumerate(Directives)) { + Directive Dir{Rec}; + std::vector Leaves = Dir.getLeafConstructs(); + + auto &List = LeafTable[Idx]; + List.resize(MaxLeafCount + 2); + List[0] = Idx; // The id of the directive itself. + List[1] = Leaves.size(); // The number of leaves to follow. + + for (int I = 0; I != MaxLeafCount; ++I) + List[I + 2] = + static_cast(I) < Leaves.size() ? DirId.at(Leaves[I]) : -1; + } - // Generate the locals. - for (Record *R : DirLang.getDirectives()) { - Directive Dir{R}; + // Some Fortran directives are delimited, i.e. they have the form of + // "directive"---"end directive". If "directive" is a compound construct, + // then the set of leaf constituents will be nonempty and the same for + // both directives. Given this set of leafs, looking up the corresponding + // compound directive should return "directive", and not "end directive". + // To avoid this problem, gather all "end directives" at the end of the + // leaf table, and only do the search on the initial segment of the table + // that excludes the "end directives". + // It's safe to find all directives whose names begin with "end ". The + // problem only exists for compound directives, like "end do simd". + // All existing directives with names starting with "end " are either + // "end directives" for an existing "directive", or leaf directives + // (such as "end declare target"). + DenseSet EndDirectives; + for (auto [Rec, Id] : DirId) { + if (Directive{Rec}.getName().starts_with_insensitive("end ")) + EndDirectives.insert(Id); + } - std::vector LeafConstructs = Dir.getLeafConstructs(); - if (LeafConstructs.empty()) - continue; + // Avoid sorting the vector array, instead sort an index array. + // It will also be useful later to create the auxiliary indexing array. + std::vector Ordering(Directives.size()); + std::iota(Ordering.begin(), Ordering.end(), 0); + + llvm::sort(Ordering, [&](int A, int B) { + auto &LeavesA = LeafTable[A]; + auto &LeavesB = LeafTable[B]; + int DirA = LeavesA[0], DirB = LeavesB[0]; + // First of all, end directives compare greater than non-end directives. + int IsEndA = EndDirectives.count(DirA), IsEndB = EndDirectives.count(DirB); + if (IsEndA != IsEndB) + return IsEndA < IsEndB; + if (LeavesA[1] == 0 && LeavesB[1] == 0) + return DirA < DirB; + return std::lexicographical_compare(&LeavesA[2], &LeavesA[2] + LeavesA[1], + &LeavesB[2], &LeavesB[2] + LeavesB[1]); + }); - std::string ListName = "leafConstructs_" + Dir.getFormattedName(); - OS << " static const " << DirectiveTypeName << ' ' << ListName - << "[] = {\n"; - for (Record *L : LeafConstructs) { - Directive LeafDir{L}; - OS << " " << getQualifiedName(LeafDir.getFormattedName()) << ",\n"; + // Emit the table + + // The directives are emitted into a scoped enum, for which the underlying + // type is `int` (by default). The code above uses `int` to store directive + // ids, so make sure that we catch it when something changes in the + // underlying type. + std::string DirectiveType = GetDirectiveType(DirLang); + OS << "\nstatic_assert(sizeof(" << DirectiveType << ") == sizeof(int));\n"; + + OS << "[[maybe_unused]] static const " << DirectiveType << ' ' << TableName + << "[][" << MaxLeafCount + 2 << "] = {\n"; + for (size_t I = 0, E = Directives.size(); I != E; ++I) { + auto &Leaves = LeafTable[Ordering[I]]; + OS << " " << GetDirectiveName(DirLang, Directives[Leaves[0]]); + OS << ", static_cast<" << DirectiveType << ">(" << Leaves[1] << "),"; + for (size_t I = 2, E = Leaves.size(); I != E; ++I) { + int Idx = Leaves[I]; + if (Idx >= 0) + OS << ' ' << GetDirectiveName(DirLang, Directives[Leaves[I]]) << ','; + else + OS << " static_cast<" << DirectiveType << ">(-1),"; } - OS << " };\n"; - ListNames.insert(std::make_pair(R, std::move(ListName))); - } - - if (!ListNames.empty()) OS << '\n'; - OS << " switch (Dir) {\n"; - for (Record *R : DirLang.getDirectives()) { - auto F = ListNames.find(R); - if (F == ListNames.end()) - continue; - - Directive Dir{R}; - OS << " case " << getQualifiedName(Dir.getFormattedName()) << ":\n"; - OS << " return " << F->second << ";\n"; } - OS << " default:\n"; - OS << " return ArrayRef<" << DirectiveTypeName << ">{};\n"; - OS << " } // switch (Dir)\n"; - OS << "}\n"; + OS << "};\n\n"; + + // Emit a marker where the first "end directive" is. + auto FirstE = llvm::find_if(Ordering, [&](int RowIdx) { + return EndDirectives.count(LeafTable[RowIdx][0]); + }); + OS << "[[maybe_unused]] static auto " << TableName + << "EndDirective = " << TableName << " + " + << std::distance(Ordering.begin(), FirstE) << ";\n\n"; + + // Emit the auxiliary index table: it's the inverse of the `Ordering` + // table above. + OS << "[[maybe_unused]] static const int " << TableName << "Ordering[] = {\n"; + OS << " "; + std::vector Reverse(Ordering.size()); + for (int I = 0, E = Ordering.size(); I != E; ++I) + Reverse[Ordering[I]] = I; + for (int Idx : Reverse) + OS << ' ' << Idx << ','; + OS << "\n};\n"; } static void GenerateGetDirectiveAssociation(const DirectiveLanguage &DirLang, @@ -1105,11 +1193,11 @@ void EmitDirectivesBasicImpl(const DirectiveLanguage &DirLang, // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) GenerateIsAllowedClause(DirLang, OS); - // getLeafConstructs(Directive D) - GenerateGetLeafConstructs(DirLang, OS); - // getDirectiveAssociation(Directive D) GenerateGetDirectiveAssociation(DirLang, OS); + + // Leaf table for getLeafConstructs, etc. + EmitLeafTable(DirLang, OS, "LeafConstructTable"); } // Generate the implemenation section for the enumeration in the directive -- GitLab From 99f42e6b88177328ebe725b5cb6d422106bbb3e6 Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Tue, 23 Apr 2024 03:51:11 +0800 Subject: [PATCH 216/357] [lldb][dap] always add column field in StackFrame body (#73393) The `column` field is mandatory in StackTraceResponse, otherwise the debugger client may raise error (e.g. VSCode can't correctly open an editor without the column field) --------- Signed-off-by: Xu Jun <693788454@qq.com> --- lldb/tools/lldb-dap/JSONUtils.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 878449a91aa6..b4a2718bbb09 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -748,9 +748,10 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame) { auto line = line_entry.GetLine(); if (line && line != LLDB_INVALID_LINE_NUMBER) object.try_emplace("line", line); + else + object.try_emplace("line", 0); auto column = line_entry.GetColumn(); - if (column && column != LLDB_INVALID_COLUMN_NUMBER) - object.try_emplace("column", column); + object.try_emplace("column", column); } else { object.try_emplace("line", 0); object.try_emplace("column", 0); -- GitLab From bcd150d2906ac83ea0ab680e981770a71c021a03 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 22 Apr 2024 19:56:11 +0000 Subject: [PATCH 217/357] [gn build] Port 40137ff0d81b --- llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn index 9648fac135b6..c78ea923aae8 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/Frontend/BUILD.gn @@ -13,6 +13,7 @@ unittest("LLVMFrontendTests") { ] sources = [ "OpenACCTest.cpp", + "OpenMPComposeTest.cpp", "OpenMPContextTest.cpp", "OpenMPIRBuilderTest.cpp", "OpenMPParsingTest.cpp", -- GitLab From 7c5854673391940d578c591c727614bf50b78301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Degioanni?= Date: Mon, 22 Apr 2024 22:03:56 +0200 Subject: [PATCH 218/357] [nfc][llvm] Fix a typo in MathExtras.h testing (#89653) I made a small typo when writing a test for MathExtras.h, sorry! --- llvm/unittests/Support/MathExtrasTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp index 218655851ca0..d09f987b9d0f 100644 --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -41,9 +41,9 @@ TEST(MathExtras, onesMask) { TEST(MathExtras, isIntN) { EXPECT_TRUE(isIntN(16, 32767)); EXPECT_FALSE(isIntN(16, 32768)); - EXPECT_TRUE(isUIntN(0, 0)); - EXPECT_FALSE(isUIntN(0, 1)); - EXPECT_FALSE(isUIntN(0, -1)); + EXPECT_TRUE(isIntN(0, 0)); + EXPECT_FALSE(isIntN(0, 1)); + EXPECT_FALSE(isIntN(0, -1)); } TEST(MathExtras, isUIntN) { -- GitLab From 83bc7b57714dc2f6b33c188f2b95a0025468ba51 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Mon, 22 Apr 2024 22:13:58 +0200 Subject: [PATCH 219/357] [libc++] Remove _LIBCPP_DISABLE_NODISCARD_EXTENSIONS and refactor the tests (#87094) This also adds a few tests that were missing. --- libcxx/.clang-format | 1 - libcxx/docs/ReleaseNotes/19.rst | 4 + libcxx/docs/UsingLibcxx.rst | 27 --- libcxx/include/__algorithm/adjacent_find.h | 6 +- libcxx/include/__algorithm/all_of.h | 2 +- libcxx/include/__algorithm/any_of.h | 2 +- libcxx/include/__algorithm/binary_search.h | 4 +- libcxx/include/__algorithm/clamp.h | 4 +- libcxx/include/__algorithm/count.h | 2 +- libcxx/include/__algorithm/count_if.h | 6 +- libcxx/include/__algorithm/equal.h | 8 +- libcxx/include/__algorithm/equal_range.h | 4 +- libcxx/include/__algorithm/find.h | 2 +- libcxx/include/__algorithm/find_end.h | 4 +- libcxx/include/__algorithm/find_first_of.h | 4 +- libcxx/include/__algorithm/find_if.h | 2 +- libcxx/include/__algorithm/find_if_not.h | 2 +- libcxx/include/__algorithm/fold.h | 10 +- libcxx/include/__algorithm/includes.h | 4 +- libcxx/include/__algorithm/is_heap.h | 4 +- libcxx/include/__algorithm/is_heap_until.h | 4 +- libcxx/include/__algorithm/is_partitioned.h | 2 +- libcxx/include/__algorithm/is_permutation.h | 10 +- libcxx/include/__algorithm/is_sorted.h | 4 +- libcxx/include/__algorithm/is_sorted_until.h | 4 +- .../__algorithm/lexicographical_compare.h | 4 +- .../lexicographical_compare_three_way.h | 4 +- libcxx/include/__algorithm/lower_bound.h | 4 +- libcxx/include/__algorithm/max.h | 8 +- libcxx/include/__algorithm/max_element.h | 4 +- libcxx/include/__algorithm/min.h | 8 +- libcxx/include/__algorithm/min_element.h | 4 +- libcxx/include/__algorithm/minmax.h | 8 +- libcxx/include/__algorithm/minmax_element.h | 7 +- libcxx/include/__algorithm/mismatch.h | 12 +- libcxx/include/__algorithm/none_of.h | 2 +- .../__algorithm/pstl_any_all_none_of.h | 6 +- .../include/__algorithm/pstl_is_partitioned.h | 2 +- .../__algorithm/ranges_adjacent_find.h | 4 +- libcxx/include/__algorithm/ranges_all_of.h | 4 +- libcxx/include/__algorithm/ranges_any_of.h | 4 +- .../__algorithm/ranges_binary_search.h | 4 +- libcxx/include/__algorithm/ranges_clamp.h | 2 +- libcxx/include/__algorithm/ranges_contains.h | 4 +- .../__algorithm/ranges_contains_subrange.h | 4 +- libcxx/include/__algorithm/ranges_count.h | 4 +- libcxx/include/__algorithm/ranges_count_if.h | 4 +- libcxx/include/__algorithm/ranges_ends_with.h | 4 +- libcxx/include/__algorithm/ranges_equal.h | 4 +- .../include/__algorithm/ranges_equal_range.h | 4 +- libcxx/include/__algorithm/ranges_find.h | 4 +- libcxx/include/__algorithm/ranges_find_end.h | 4 +- .../__algorithm/ranges_find_first_of.h | 4 +- libcxx/include/__algorithm/ranges_find_if.h | 4 +- .../include/__algorithm/ranges_find_if_not.h | 4 +- libcxx/include/__algorithm/ranges_includes.h | 4 +- libcxx/include/__algorithm/ranges_is_heap.h | 4 +- .../__algorithm/ranges_is_heap_until.h | 4 +- .../__algorithm/ranges_is_partitioned.h | 4 +- .../__algorithm/ranges_is_permutation.h | 4 +- libcxx/include/__algorithm/ranges_is_sorted.h | 4 +- .../__algorithm/ranges_is_sorted_until.h | 4 +- .../ranges_lexicographical_compare.h | 4 +- .../include/__algorithm/ranges_lower_bound.h | 4 +- libcxx/include/__algorithm/ranges_max.h | 6 +- .../include/__algorithm/ranges_max_element.h | 4 +- libcxx/include/__algorithm/ranges_min.h | 6 +- .../include/__algorithm/ranges_min_element.h | 4 +- libcxx/include/__algorithm/ranges_minmax.h | 6 +- .../__algorithm/ranges_minmax_element.h | 4 +- libcxx/include/__algorithm/ranges_mismatch.h | 4 +- libcxx/include/__algorithm/ranges_none_of.h | 4 +- libcxx/include/__algorithm/ranges_remove.h | 4 +- libcxx/include/__algorithm/ranges_remove_if.h | 4 +- libcxx/include/__algorithm/ranges_search.h | 4 +- libcxx/include/__algorithm/ranges_search_n.h | 4 +- .../include/__algorithm/ranges_starts_with.h | 4 +- libcxx/include/__algorithm/ranges_unique.h | 4 +- .../include/__algorithm/ranges_upper_bound.h | 4 +- libcxx/include/__algorithm/remove.h | 2 +- libcxx/include/__algorithm/remove_if.h | 2 +- libcxx/include/__algorithm/search.h | 6 +- libcxx/include/__algorithm/search_n.h | 4 +- libcxx/include/__algorithm/unique.h | 6 +- libcxx/include/__algorithm/upper_bound.h | 4 +- libcxx/include/__bit/bit_cast.h | 2 +- libcxx/include/__bit/bit_ceil.h | 4 +- libcxx/include/__bit/bit_floor.h | 2 +- libcxx/include/__bit/bit_width.h | 2 +- libcxx/include/__bit/byteswap.h | 2 +- libcxx/include/__bit/countl.h | 4 +- libcxx/include/__bit/countr.h | 4 +- libcxx/include/__bit/has_single_bit.h | 2 +- libcxx/include/__bit/popcount.h | 2 +- libcxx/include/__chrono/leap_second.h | 4 +- libcxx/include/__chrono/time_zone.h | 8 +- libcxx/include/__chrono/time_zone_link.h | 10 +- libcxx/include/__chrono/tzdb.h | 4 +- libcxx/include/__chrono/tzdb_list.h | 21 +- libcxx/include/__config | 16 +- libcxx/include/__filesystem/path.h | 2 +- libcxx/include/__format/format_functions.h | 30 ++- libcxx/include/__functional/identity.h | 2 +- libcxx/include/__iterator/empty.h | 8 +- libcxx/include/__math/abs.h | 8 +- libcxx/include/__math/copysign.h | 7 +- libcxx/include/__math/min_max.h | 16 +- libcxx/include/__math/roots.h | 8 +- libcxx/include/__math/rounding_functions.h | 48 ++--- libcxx/include/__math/traits.h | 46 ++--- libcxx/include/__memory/allocator.h | 10 +- libcxx/include/__memory/allocator_traits.h | 6 +- libcxx/include/__memory/temporary_buffer.h | 2 +- .../__memory_resource/memory_resource.h | 5 +- .../__memory_resource/polymorphic_allocator.h | 2 +- libcxx/include/__mutex/lock_guard.h | 6 +- libcxx/include/__node_handle | 2 +- libcxx/include/__ranges/as_rvalue_view.h | 4 +- libcxx/include/__ranges/chunk_by_view.h | 4 +- libcxx/include/__ranges/drop_view.h | 4 +- libcxx/include/__ranges/repeat_view.h | 4 +- libcxx/include/__ranges/split_view.h | 4 +- libcxx/include/__ranges/take_view.h | 4 +- libcxx/include/__ranges/to.h | 8 +- libcxx/include/__utility/as_const.h | 2 +- libcxx/include/__utility/forward.h | 4 +- libcxx/include/__utility/move.h | 4 +- libcxx/include/__utility/to_underlying.h | 2 +- libcxx/include/array | 4 +- libcxx/include/barrier | 4 +- libcxx/include/cstddef | 2 +- libcxx/include/deque | 2 +- libcxx/include/forward_list | 2 +- libcxx/include/future | 10 +- libcxx/include/limits | 126 ++++++------ libcxx/include/list | 2 +- libcxx/include/map | 4 +- libcxx/include/math.h | 8 +- libcxx/include/module.modulemap | 5 +- libcxx/include/new | 24 +-- libcxx/include/queue | 4 +- libcxx/include/regex | 2 +- libcxx/include/scoped_allocator | 4 +- libcxx/include/set | 4 +- libcxx/include/stack | 2 +- libcxx/include/stdlib.h | 12 +- libcxx/include/string | 2 +- libcxx/include/string_view | 2 +- libcxx/include/unordered_map | 4 +- libcxx/include/unordered_set | 4 +- libcxx/include/vector | 4 +- libcxx/src/tzdb.cpp | 4 +- ...ify.cpp => algorithm.nodiscard.verify.cpp} | 159 +++++++++------ .../diagnostics/array.nodiscard.verify.cpp | 23 +++ ...ns.verify.cpp => bit.nodiscard.verify.cpp} | 2 + .../bit.nodiscard_extensions.compile.pass.cpp | 34 ---- ...verify.cpp => chrono.nodiscard.verify.cpp} | 0 ...rono.nodiscard_extensions.compile.pass.cpp | 69 ------- ....verify.cpp => cmath.nodiscard.verify.cpp} | 2 + .../diagnostics/cstddef.nodiscard.verify.cpp} | 15 +- .../diagnostics/cstdlib.nodiscard.verify.cpp | 25 +++ .../diagnostics/deque.nodiscard.verify.cpp | 18 ++ .../filesystem.nodiscard.verify.cpp | 19 ++ ...verify.cpp => format.nodiscard.verify.cpp} | 0 ...rmat.nodiscard_extensions.compile.pass.cpp | 50 ----- .../forward_list.nodiscard.verify.cpp | 18 ++ ...ss.cpp => functional.nodiscard.verify.cpp} | 16 +- .../diagnostics/future.nodiscard.verify.cpp | 22 ++ .../diagnostics/iterator.nodiscard.verify.cpp | 26 +++ ...verify.cpp => limits.nodiscard.verify.cpp} | 0 ...mits.nodiscard_extensions.compile.pass.cpp | 71 ------- .../diagnostics/list.nodiscard.verify.cpp | 18 ++ .../diagnostics/map.nodiscard.verify.cpp | 23 +++ .../diagnostics/memory.nodiscard.verify.cpp | 53 +++++ .../memory_resource.nodiscard.verify.cpp | 25 +++ .../diagnostics/mutex.nodiscard.verify.cpp | 25 +++ .../diagnostics/new.nodiscard.verify.cpp | 35 ++++ .../node_handle.nodiscard.verify.cpp | 18 ++ .../nodiscard_extensions.compile.pass.cpp | 188 ------------------ ...s.verify.cpp => pstl.nodiscard.verify.cpp} | 9 +- ...pstl.nodiscard_extensions.compile.pass.cpp | 28 --- .../diagnostics/queue.nodiscard.verify.cpp | 23 +++ .../diagnostics/ranges.nodiscard.verify.cpp | 59 ++++++ ...nges.nodiscard_extensions.compile.pass.cpp | 101 ---------- .../ranges.nodiscard_extensions.verify.cpp | 111 ----------- ....verify.cpp => regex.nodiscard.verify.cpp} | 15 +- .../scoped_allocator.nodiscard.verify.cpp | 22 ++ .../diagnostics/set.nodiscard.verify.cpp | 23 +++ .../diagnostics/stack.nodiscard.verify.cpp | 18 ++ .../diagnostics/string.nodiscard.verify.cpp | 18 ++ .../string_view.nodiscard.verify.cpp | 18 ++ .../unordered_map.nodiscard.verify.cpp | 25 +++ .../unordered_set.nodiscard.verify.cpp | 25 +++ .../diagnostics/utility.nodiscard.verify.cpp | 35 ++++ .../diagnostics/vector.nodiscard.verify.cpp | 23 +++ ...w_adaptors.nodiscard_extensions.verify.cpp | 22 -- .../adaptor.nodiscard.verify.cpp | 26 --- .../to.nodiscard.verify.cpp | 29 --- 198 files changed, 1224 insertions(+), 1331 deletions(-) rename libcxx/test/libcxx/diagnostics/{nodiscard_extensions.verify.cpp => algorithm.nodiscard.verify.cpp} (56%) create mode 100644 libcxx/test/libcxx/diagnostics/array.nodiscard.verify.cpp rename libcxx/test/libcxx/diagnostics/{bit.nodiscard_extensions.verify.cpp => bit.nodiscard.verify.cpp} (98%) delete mode 100644 libcxx/test/libcxx/diagnostics/bit.nodiscard_extensions.compile.pass.cpp rename libcxx/test/libcxx/diagnostics/{chrono.nodiscard_extensions.verify.cpp => chrono.nodiscard.verify.cpp} (100%) delete mode 100644 libcxx/test/libcxx/diagnostics/chrono.nodiscard_extensions.compile.pass.cpp rename libcxx/test/libcxx/diagnostics/{math_nodiscard_extensions.verify.cpp => cmath.nodiscard.verify.cpp} (99%) rename libcxx/test/{std/language.support/support.dynamic/ptr.launder/launder.nodiscard.verify.cpp => libcxx/diagnostics/cstddef.nodiscard.verify.cpp} (60%) create mode 100644 libcxx/test/libcxx/diagnostics/cstdlib.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/deque.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/filesystem.nodiscard.verify.cpp rename libcxx/test/libcxx/diagnostics/{format.nodiscard_extensions.verify.cpp => format.nodiscard.verify.cpp} (100%) delete mode 100644 libcxx/test/libcxx/diagnostics/format.nodiscard_extensions.compile.pass.cpp create mode 100644 libcxx/test/libcxx/diagnostics/forward_list.nodiscard.verify.cpp rename libcxx/test/libcxx/diagnostics/{nodiscard.pass.cpp => functional.nodiscard.verify.cpp} (55%) create mode 100644 libcxx/test/libcxx/diagnostics/future.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/iterator.nodiscard.verify.cpp rename libcxx/test/libcxx/diagnostics/{limits.nodiscard_extensions.verify.cpp => limits.nodiscard.verify.cpp} (100%) delete mode 100644 libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.compile.pass.cpp create mode 100644 libcxx/test/libcxx/diagnostics/list.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/map.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/memory_resource.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/mutex.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/new.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/node_handle.nodiscard.verify.cpp delete mode 100644 libcxx/test/libcxx/diagnostics/nodiscard_extensions.compile.pass.cpp rename libcxx/test/libcxx/diagnostics/{pstl.nodiscard_extensions.verify.cpp => pstl.nodiscard.verify.cpp} (62%) delete mode 100644 libcxx/test/libcxx/diagnostics/pstl.nodiscard_extensions.compile.pass.cpp create mode 100644 libcxx/test/libcxx/diagnostics/queue.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/ranges.nodiscard.verify.cpp delete mode 100644 libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.compile.pass.cpp delete mode 100644 libcxx/test/libcxx/diagnostics/ranges.nodiscard_extensions.verify.cpp rename libcxx/test/libcxx/diagnostics/{nodiscard_aftercxx17.verify.cpp => regex.nodiscard.verify.cpp} (52%) create mode 100644 libcxx/test/libcxx/diagnostics/scoped_allocator.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/set.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/stack.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/string.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/string_view.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/unordered_map.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/unordered_set.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/utility.nodiscard.verify.cpp create mode 100644 libcxx/test/libcxx/diagnostics/vector.nodiscard.verify.cpp delete mode 100644 libcxx/test/libcxx/diagnostics/view_adaptors.nodiscard_extensions.verify.cpp delete mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk.by/adaptor.nodiscard.verify.cpp delete mode 100644 libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.nodiscard.verify.cpp diff --git a/libcxx/.clang-format b/libcxx/.clang-format index c37ab817bca9..871920f15b5b 100644 --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -44,7 +44,6 @@ AttributeMacros: [ '_LIBCPP_NO_SANITIZE', '_LIBCPP_NO_UNIQUE_ADDRESS', '_LIBCPP_NOALIAS', - '_LIBCPP_NODISCARD_EXT', '_LIBCPP_NODISCARD', '_LIBCPP_NORETURN', '_LIBCPP_OVERRIDABLE_FUNC_VIS', diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 53cc7a77d1af..b466b4cd8140 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -79,6 +79,10 @@ Deprecations and Removals in language modes prior to C++20. If you are using these features prior to C++20, please update to ``-std=c++20``. In LLVM 20, the C++20 synchronization library will be removed entirely in language modes prior to C++20. +- ``_LIBCPP_DISABLE_NODISCARD_EXT`` has been removed. ``[[nodiscard]]`` applications are now unconditional. + This decision is based on LEWGs discussion on `P3122 ` and `P3162 ` + to not use ``[[nodiscard]]`` in the standard. + - TODO: The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable that was used to enable the safe mode has been deprecated and setting it triggers an error; use the ``LIBCXX_HARDENING_MODE`` CMake variable with the value ``extensive`` instead. Similarly, the ``_LIBCPP_ENABLE_ASSERTIONS`` macro has been deprecated (setting it to ``1`` still enables the extensive mode in diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index 8f945656de1c..e7aaf4e1fbcf 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -196,10 +196,6 @@ safety annotations. replacement scenarios from working, e.g. replacing `operator new` and expecting a non-replaced `operator new[]` to call the replaced `operator new`. -**_LIBCPP_DISABLE_NODISCARD_EXT**: - This macro disables library-extensions of ``[[nodiscard]]``. - See :ref:`Extended Applications of [[nodiscard]] ` for more information. - **_LIBCPP_DISABLE_DEPRECATION_WARNINGS**: This macro disables warnings when using deprecated components. For example, using `std::auto_ptr` when compiling in C++11 mode will normally trigger a @@ -279,29 +275,6 @@ Libc++ Extensions This section documents various extensions provided by libc++, how they're provided, and any information regarding how to use them. -.. _nodiscard extension: - -Extended applications of ``[[nodiscard]]`` ------------------------------------------- - -The ``[[nodiscard]]`` attribute is intended to help users find bugs where -function return values are ignored when they shouldn't be. After C++17 the -C++ standard has started to declared such library functions as ``[[nodiscard]]``. -However, this application is limited and applies only to dialects after C++17. -Users who want help diagnosing misuses of STL functions may desire a more -liberal application of ``[[nodiscard]]``. - -For this reason libc++ provides an extension that does just that! The -extension is enabled by default and can be disabled by defining ``_LIBCPP_DISABLE_NODISCARD_EXT``. -The extended applications of ``[[nodiscard]]`` takes two forms: - -1. Backporting ``[[nodiscard]]`` to entities declared as such by the - standard in newer dialects, but not in the present one. - -2. Extended applications of ``[[nodiscard]]``, at the library's discretion, - applied to entities never declared as such by the standard. You can find - all such applications by grepping for ``_LIBCPP_NODISCARD_EXT``. - Extended integral type support ------------------------------ diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h index 7819e2cf49b9..6f15456e3a4d 100644 --- a/libcxx/include/__algorithm/adjacent_find.h +++ b/libcxx/include/__algorithm/adjacent_find.h @@ -26,7 +26,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { if (__first == __last) return __first; @@ -40,13 +40,13 @@ __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { return std::__adjacent_find(std::move(__first), std::move(__last), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { return std::adjacent_find(std::move(__first), std::move(__last), __equal_to()); } diff --git a/libcxx/include/__algorithm/all_of.h b/libcxx/include/__algorithm/all_of.h index 237f8495c645..ec84eea75929 100644 --- a/libcxx/include/__algorithm/all_of.h +++ b/libcxx/include/__algorithm/all_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/any_of.h b/libcxx/include/__algorithm/any_of.h index 8ba7aae2b225..b5ff778c4171 100644 --- a/libcxx/include/__algorithm/any_of.h +++ b/libcxx/include/__algorithm/any_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/binary_search.h b/libcxx/include/__algorithm/binary_search.h index 7a77d7b5447b..6065fc37274d 100644 --- a/libcxx/include/__algorithm/binary_search.h +++ b/libcxx/include/__algorithm/binary_search.h @@ -22,14 +22,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { __first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp); return __first != __last && !__comp(__value, *__first); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::binary_search(__first, __last, __value, __less<>()); } diff --git a/libcxx/include/__algorithm/clamp.h b/libcxx/include/__algorithm/clamp.h index 003bf70dd4f0..1a5a3d0744be 100644 --- a/libcxx/include/__algorithm/clamp.h +++ b/libcxx/include/__algorithm/clamp.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& +[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, _LIBCPP_LIFETIMEBOUND const _Tp& __lo, _LIBCPP_LIFETIMEBOUND const _Tp& __hi, @@ -31,7 +31,7 @@ clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& +[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, _LIBCPP_LIFETIMEBOUND const _Tp& __lo, _LIBCPP_LIFETIMEBOUND const _Tp& __hi) { diff --git a/libcxx/include/__algorithm/count.h b/libcxx/include/__algorithm/count.h index 23a7d3c4dcfe..1cfe7f631ac1 100644 --- a/libcxx/include/__algorithm/count.h +++ b/libcxx/include/__algorithm/count.h @@ -79,7 +79,7 @@ __count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __l } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> count(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __identity __proj; return std::__count<_ClassicAlgPolicy>(__first, __last, __value, __proj); diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h index 04f52b894f8b..25782069d032 100644 --- a/libcxx/include/__algorithm/count_if.h +++ b/libcxx/include/__algorithm/count_if.h @@ -20,9 +20,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - typename iterator_traits<_InputIterator>::difference_type - count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +typename iterator_traits<_InputIterator>::difference_type +count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { typename iterator_traits<_InputIterator>::difference_type __r(0); for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h index 1341d9e4159b..bfc8f72f6eb1 100644 --- a/libcxx/include/__algorithm/equal.h +++ b/libcxx/include/__algorithm/equal.h @@ -55,14 +55,14 @@ __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { return std::__equal_iter_impl( std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::equal(__first1, __last1, __first2, __equal_to()); } @@ -96,7 +96,7 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -119,7 +119,7 @@ equal(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::equal(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h index 2b086abf1794..09bbf8f00602 100644 --- a/libcxx/include/__algorithm/equal_range.h +++ b/libcxx/include/__algorithm/equal_range.h @@ -60,7 +60,7 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); @@ -73,7 +73,7 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::equal_range(std::move(__first), std::move(__last), __value, __less<>()); } diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h index 7d7631b6e98a..d60356873132 100644 --- a/libcxx/include/__algorithm/find.h +++ b/libcxx/include/__algorithm/find.h @@ -169,7 +169,7 @@ struct __find_segment { // public API template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __identity __proj; return std::__rewrap_iter( diff --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h index 4c26891666b2..7e08e7953534 100644 --- a/libcxx/include/__algorithm/find_end.h +++ b/libcxx/include/__algorithm/find_end.h @@ -205,7 +205,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Fo } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -215,7 +215,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::find_end(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/find_first_of.h b/libcxx/include/__algorithm/find_first_of.h index 14271cccc42b..6b99f562f880 100644 --- a/libcxx/include/__algorithm/find_first_of.h +++ b/libcxx/include/__algorithm/find_first_of.h @@ -35,7 +35,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_fir } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -45,7 +45,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/find_if.h b/libcxx/include/__algorithm/find_if.h index 09a39f646351..22092d352b06 100644 --- a/libcxx/include/__algorithm/find_if.h +++ b/libcxx/include/__algorithm/find_if.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/find_if_not.h b/libcxx/include/__algorithm/find_if_not.h index bf29ebb7cdd9..cc2001967f0c 100644 --- a/libcxx/include/__algorithm/find_if_not.h +++ b/libcxx/include/__algorithm/find_if_not.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/fold.h b/libcxx/include/__algorithm/fold.h index 1a9d76b50d83..255658f52324 100644 --- a/libcxx/include/__algorithm/fold.h +++ b/libcxx/include/__algorithm/fold.h @@ -78,8 +78,7 @@ concept __indirectly_binary_left_foldable = struct __fold_left_with_iter { template _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto - operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { using _Up = decay_t>>; if (__first == __last) { @@ -95,7 +94,7 @@ struct __fold_left_with_iter { } template > _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { auto __result = operator()(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)); using _Up = decay_t>>; @@ -107,13 +106,12 @@ inline constexpr auto fold_left_with_iter = __fold_left_with_iter(); struct __fold_left { template _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto - operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { return fold_left_with_iter(std::move(__first), std::move(__last), std::move(__init), std::ref(__f)).value; } template > _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { return fold_left_with_iter(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)).value; } }; diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h index 05d45365eb80..62af03c37426 100644 --- a/libcxx/include/__algorithm/includes.h +++ b/libcxx/include/__algorithm/includes.h @@ -47,7 +47,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __includes( } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -67,7 +67,7 @@ includes(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::includes(std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __less<>()); } diff --git a/libcxx/include/__algorithm/is_heap.h b/libcxx/include/__algorithm/is_heap.h index 0d2d43c2c3ab..c589b804a5dc 100644 --- a/libcxx/include/__algorithm/is_heap.h +++ b/libcxx/include/__algorithm/is_heap.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { return std::is_heap(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/is_heap_until.h b/libcxx/include/__algorithm/is_heap_until.h index 1eae3b86b90d..a174f2453cfc 100644 --- a/libcxx/include/__algorithm/is_heap_until.h +++ b/libcxx/include/__algorithm/is_heap_until.h @@ -46,13 +46,13 @@ __is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) { return std::__is_heap_until(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/is_partitioned.h b/libcxx/include/__algorithm/is_partitioned.h index 71feed332060..1f7c8b0b267e 100644 --- a/libcxx/include/__algorithm/is_partitioned.h +++ b/libcxx/include/__algorithm/is_partitioned.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h index 4226151222bb..2ddfb32a212b 100644 --- a/libcxx/include/__algorithm/is_permutation.h +++ b/libcxx/include/__algorithm/is_permutation.h @@ -113,7 +113,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl( // 2+1 iterators, predicate. Not used by range algorithms. template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( _ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _BinaryPredicate&& __pred) { // Shorten sequences as much as possible by lopping of any equal prefix. for (; __first1 != __last1; ++__first1, (void)++__first2) { @@ -247,7 +247,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( // 2+1 iterators, predicate template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) { static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, "The predicate has to be callable"); @@ -257,7 +257,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool i // 2+1 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { return std::is_permutation(__first1, __last1, __first2, __equal_to()); } @@ -266,7 +266,7 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt // 2+2 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::__is_permutation<_ClassicAlgPolicy>( std::move(__first1), @@ -280,7 +280,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 // 2+2 iterators, predicate template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, diff --git a/libcxx/include/__algorithm/is_sorted.h b/libcxx/include/__algorithm/is_sorted.h index 1874cace882c..3befb1ac9c26 100644 --- a/libcxx/include/__algorithm/is_sorted.h +++ b/libcxx/include/__algorithm/is_sorted.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last) { return std::is_sorted(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/is_sorted_until.h b/libcxx/include/__algorithm/is_sorted_until.h index 7450440df2d8..53a49f00de31 100644 --- a/libcxx/include/__algorithm/is_sorted_until.h +++ b/libcxx/include/__algorithm/is_sorted_until.h @@ -35,13 +35,13 @@ __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __ } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { return std::is_sorted_until(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/lexicographical_compare.h b/libcxx/include/__algorithm/lexicographical_compare.h index 3efd8e24bf6c..edc29e269c88 100644 --- a/libcxx/include/__algorithm/lexicographical_compare.h +++ b/libcxx/include/__algorithm/lexicographical_compare.h @@ -37,7 +37,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __lexicographical_compa } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -47,7 +47,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>()); } diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h index 50ebdc647a97..a5872e90cf8d 100644 --- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h +++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h @@ -90,7 +90,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_pa } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp __comp) -> decltype(__comp(*__first1, *__first2)) { static_assert(__comparison_category, @@ -110,7 +110,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compa } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::lexicographical_compare_three_way( std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::compare_three_way()); diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h index 8f57f3592c4b..8fd355a7cfc4 100644 --- a/libcxx/include/__algorithm/lower_bound.h +++ b/libcxx/include/__algorithm/lower_bound.h @@ -47,7 +47,7 @@ __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); auto __proj = std::__identity(); @@ -55,7 +55,7 @@ lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::lower_bound(__first, __last, __value, __less<>()); } diff --git a/libcxx/include/__algorithm/max.h b/libcxx/include/__algorithm/max.h index 8171677f155c..d4c99f6f3643 100644 --- a/libcxx/include/__algorithm/max.h +++ b/libcxx/include/__algorithm/max.h @@ -25,13 +25,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__a, __b) ? __b : __a; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::max(__a, __b, __less<>()); } @@ -39,13 +39,13 @@ max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t, _Compare __comp) { return *std::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { return *std::max_element(__t.begin(), __t.end(), __less<>()); } diff --git a/libcxx/include/__algorithm/max_element.h b/libcxx/include/__algorithm/max_element.h index f1d4f1cd0938..c036726cbccd 100644 --- a/libcxx/include/__algorithm/max_element.h +++ b/libcxx/include/__algorithm/max_element.h @@ -35,13 +35,13 @@ __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { return std::max_element(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/min.h b/libcxx/include/__algorithm/min.h index 919508486fd5..1bafad8a461e 100644 --- a/libcxx/include/__algorithm/min.h +++ b/libcxx/include/__algorithm/min.h @@ -25,13 +25,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? __b : __a; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::min(__a, __b, __less<>()); } @@ -39,13 +39,13 @@ min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t, _Compare __comp) { return *std::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { return *std::min_element(__t.begin(), __t.end(), __less<>()); } diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h index c576d665601d..65f3594d630c 100644 --- a/libcxx/include/__algorithm/min_element.h +++ b/libcxx/include/__algorithm/min_element.h @@ -48,7 +48,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element(_Iter __ } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); @@ -59,7 +59,7 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last) { return std::min_element(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/minmax.h b/libcxx/include/__algorithm/minmax.h index 5227b8857175..9feda2b4c0da 100644 --- a/libcxx/include/__algorithm/minmax.h +++ b/libcxx/include/__algorithm/minmax.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? pair(__b, __a) : pair(__a, __b); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::minmax(__a, __b, __less<>()); } @@ -38,7 +38,7 @@ minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __ #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) { static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable"); __identity __proj; @@ -47,7 +47,7 @@ minmax(initializer_list<_Tp> __t, _Compare __comp) { } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t) { return std::minmax(__t, __less<>()); } diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h index ff8cda321cef..43cb23347c34 100644 --- a/libcxx/include/__algorithm/minmax_element.h +++ b/libcxx/include/__algorithm/minmax_element.h @@ -79,7 +79,7 @@ __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator"); @@ -90,9 +90,8 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - pair<_ForwardIterator, _ForwardIterator> - minmax_element(_ForwardIterator __first, _ForwardIterator __last) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> +minmax_element(_ForwardIterator __first, _ForwardIterator __last) { return std::minmax_element(__first, __last, __less<>()); } diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h index 4ada29eabc47..c2b3f8938f71 100644 --- a/libcxx/include/__algorithm/mismatch.h +++ b/libcxx/include/__algorithm/mismatch.h @@ -122,7 +122,7 @@ __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __ #endif // _LIBCPP_VECTORIZE_ALGORITHMS template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { __identity __proj; auto __res = std::__mismatch( @@ -131,14 +131,14 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::mismatch(__first1, __last1, __first2, __equal_to()); } #if _LIBCPP_STD_VER >= 14 template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { while (__first1 != __last1 && __first2 != __last2) { if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) @@ -150,14 +150,14 @@ template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { auto __len = std::min(__last1 - __first1, __last2 - __first2); return std::__mismatch(__first1, __first1 + __len, __first2, __pred, __proj1, __proj2); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -176,7 +176,7 @@ mismatch(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::mismatch(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/libcxx/include/__algorithm/none_of.h b/libcxx/include/__algorithm/none_of.h index ce59187a3a65..50841ba17cc6 100644 --- a/libcxx/include/__algorithm/none_of.h +++ b/libcxx/include/__algorithm/none_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/libcxx/include/__algorithm/pstl_any_all_none_of.h b/libcxx/include/__algorithm/pstl_any_all_none_of.h index 911a7e42b3fa..e27463dab8a3 100644 --- a/libcxx/include/__algorithm/pstl_any_all_none_of.h +++ b/libcxx/include/__algorithm/pstl_any_all_none_of.h @@ -58,7 +58,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "any_of requires a ForwardIterator"); auto __res = std::__any_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); @@ -97,7 +97,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "all_of requires a ForwardIterator"); auto __res = std::__all_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); @@ -134,7 +134,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "none_of requires a ForwardIterator"); auto __res = std::__none_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); diff --git a/libcxx/include/__algorithm/pstl_is_partitioned.h b/libcxx/include/__algorithm/pstl_is_partitioned.h index c016b388e378..2dd5cf3ca2a2 100644 --- a/libcxx/include/__algorithm/pstl_is_partitioned.h +++ b/libcxx/include/__algorithm/pstl_is_partitioned.h @@ -61,7 +61,7 @@ template , enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "is_partitioned requires ForwardIterators"); auto __res = std::__is_partitioned(__policy, std::move(__first), std::move(__last), std::move(__pred)); diff --git a/libcxx/include/__algorithm/ranges_adjacent_find.h b/libcxx/include/__algorithm/ranges_adjacent_find.h index a10b04167ede..3c54f723310a 100644 --- a/libcxx/include/__algorithm/ranges_adjacent_find.h +++ b/libcxx/include/__algorithm/ranges_adjacent_find.h @@ -53,7 +53,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_binary_predicate, projected<_Iter, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -62,7 +62,7 @@ struct __fn { class _Proj = identity, indirect_binary_predicate, _Proj>, projected, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_all_of.h b/libcxx/include/__algorithm/ranges_all_of.h index 8976541d590c..2f603b32f32d 100644 --- a/libcxx/include/__algorithm/ranges_all_of.h +++ b/libcxx/include/__algorithm/ranges_all_of.h @@ -45,7 +45,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -53,7 +53,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_any_of.h b/libcxx/include/__algorithm/ranges_any_of.h index 7c775f5f64de..205fcecc086e 100644 --- a/libcxx/include/__algorithm/ranges_any_of.h +++ b/libcxx/include/__algorithm/ranges_any_of.h @@ -45,7 +45,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -53,7 +53,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_binary_search.h b/libcxx/include/__algorithm/ranges_binary_search.h index f3b7842d5ccc..1ef2bd62b599 100644 --- a/libcxx/include/__algorithm/ranges_binary_search.h +++ b/libcxx/include/__algorithm/ranges_binary_search.h @@ -39,7 +39,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); @@ -49,7 +49,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index f5ef5fd7f26e..e6181ef9435e 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -35,7 +35,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( const _Type& __value, const _Type& __low, const _Type& __high, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( !bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), diff --git a/libcxx/include/__algorithm/ranges_contains.h b/libcxx/include/__algorithm/ranges_contains.h index 00d0e5401988..4836c3baed17 100644 --- a/libcxx/include/__algorithm/ranges_contains.h +++ b/libcxx/include/__algorithm/ranges_contains.h @@ -37,14 +37,14 @@ namespace __contains { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) { return ranges::find(std::move(__first), __last, __value, std::ref(__proj)) != __last; } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) { return ranges::find(ranges::begin(__range), ranges::end(__range), __value, std::ref(__proj)) != ranges::end(__range); diff --git a/libcxx/include/__algorithm/ranges_contains_subrange.h b/libcxx/include/__algorithm/ranges_contains_subrange.h index bc5a86ce3d69..4398c457fd05 100644 --- a/libcxx/include/__algorithm/ranges_contains_subrange.h +++ b/libcxx/include/__algorithm/ranges_contains_subrange.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -67,7 +67,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { if constexpr (sized_range<_Range2>) { if (ranges::size(__range2) == 0) diff --git a/libcxx/include/__algorithm/ranges_count.h b/libcxx/include/__algorithm/ranges_count.h index a8965c1b961f..4f3511743870 100644 --- a/libcxx/include/__algorithm/ranges_count.h +++ b/libcxx/include/__algorithm/ranges_count.h @@ -38,14 +38,14 @@ namespace __count { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { return std::__count<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { return std::__count<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __proj); } diff --git a/libcxx/include/__algorithm/ranges_count_if.h b/libcxx/include/__algorithm/ranges_count_if.h index 71b942dd5322..5f2396ff7d53 100644 --- a/libcxx/include/__algorithm/ranges_count_if.h +++ b/libcxx/include/__algorithm/ranges_count_if.h @@ -50,7 +50,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -58,7 +58,7 @@ struct __fn { template , _Proj>> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_ends_with.h b/libcxx/include/__algorithm/ranges_ends_with.h index bb01918326b8..06efdef36b7c 100644 --- a/libcxx/include/__algorithm/ranges_ends_with.h +++ b/libcxx/include/__algorithm/ranges_ends_with.h @@ -133,7 +133,7 @@ struct __fn { requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) && (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) && indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -152,7 +152,7 @@ struct __fn { class _Proj2 = identity> requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) && indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { auto __n1 = ranges::size(__range1); diff --git a/libcxx/include/__algorithm/ranges_equal.h b/libcxx/include/__algorithm/ranges_equal.h index 31c7ee261da6..edbd0e3641c1 100644 --- a/libcxx/include/__algorithm/ranges_equal.h +++ b/libcxx/include/__algorithm/ranges_equal.h @@ -44,7 +44,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -74,7 +74,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) diff --git a/libcxx/include/__algorithm/ranges_equal_range.h b/libcxx/include/__algorithm/ranges_equal_range.h index 4c1c3834ba9f..4a308e016b54 100644 --- a/libcxx/include/__algorithm/ranges_equal_range.h +++ b/libcxx/include/__algorithm/ranges_equal_range.h @@ -46,7 +46,7 @@ struct __fn { class _Tp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__equal_range<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; @@ -56,7 +56,7 @@ struct __fn { class _Tp, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__equal_range<_RangeAlgPolicy>(ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); diff --git a/libcxx/include/__algorithm/ranges_find.h b/libcxx/include/__algorithm/ranges_find.h index 7459fad717a5..e1383eb4b071 100644 --- a/libcxx/include/__algorithm/ranges_find.h +++ b/libcxx/include/__algorithm/ranges_find.h @@ -52,14 +52,14 @@ struct __fn { template _Sp, class _Tp, class _Proj = identity> requires indirect_binary_predicate, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { return __find_unwrap(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { return __find_unwrap(ranges::begin(__r), ranges::end(__r), __value, __proj); } diff --git a/libcxx/include/__algorithm/ranges_find_end.h b/libcxx/include/__algorithm/ranges_find_end.h index 0bda4f3e1cea..e49e66dd4ac0 100644 --- a/libcxx/include/__algorithm/ranges_find_end.h +++ b/libcxx/include/__algorithm/ranges_find_end.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -72,7 +72,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_find_first_of.h b/libcxx/include/__algorithm/ranges_find_first_of.h index 63a7b8335faa..d92d9686bc44 100644 --- a/libcxx/include/__algorithm/ranges_find_first_of.h +++ b/libcxx/include/__algorithm/ranges_find_first_of.h @@ -60,7 +60,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -78,7 +78,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __find_first_of_impl( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_find_if.h b/libcxx/include/__algorithm/ranges_find_if.h index 52ae55ce96c3..888f9ec3cb2d 100644 --- a/libcxx/include/__algorithm/ranges_find_if.h +++ b/libcxx/include/__algorithm/ranges_find_if.h @@ -48,13 +48,13 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_find_if_not.h b/libcxx/include/__algorithm/ranges_find_if_not.h index 60c6796cbbfc..ec19545b5a1b 100644 --- a/libcxx/include/__algorithm/ranges_find_if_not.h +++ b/libcxx/include/__algorithm/ranges_find_if_not.h @@ -40,14 +40,14 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) -> bool { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) -> bool { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj); diff --git a/libcxx/include/__algorithm/ranges_includes.h b/libcxx/include/__algorithm/ranges_includes.h index 0bc4c043bd18..c4c3b8ed088d 100644 --- a/libcxx/include/__algorithm/ranges_includes.h +++ b/libcxx/include/__algorithm/ranges_includes.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -69,7 +69,7 @@ struct __fn { class _Proj2 = identity, indirect_strict_weak_order, _Proj1>, projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return std::__includes( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_is_heap.h b/libcxx/include/__algorithm/ranges_is_heap.h index 122368c90d92..3d9e18ce1d90 100644 --- a/libcxx/include/__algorithm/ranges_is_heap.h +++ b/libcxx/include/__algorithm/ranges_is_heap.h @@ -51,7 +51,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -59,7 +59,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_is_heap_until.h b/libcxx/include/__algorithm/ranges_is_heap_until.h index b2705d37a6d3..7a2e1fc7705b 100644 --- a/libcxx/include/__algorithm/ranges_is_heap_until.h +++ b/libcxx/include/__algorithm/ranges_is_heap_until.h @@ -51,7 +51,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -59,7 +59,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_is_partitioned.h b/libcxx/include/__algorithm/ranges_is_partitioned.h index c6a585c9f510..5be6fba46fd9 100644 --- a/libcxx/include/__algorithm/ranges_is_partitioned.h +++ b/libcxx/include/__algorithm/ranges_is_partitioned.h @@ -57,7 +57,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __is_partitioned_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -65,7 +65,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __is_partitioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_is_permutation.h b/libcxx/include/__algorithm/ranges_is_permutation.h index e0423d722b5b..1f8d67007a57 100644 --- a/libcxx/include/__algorithm/ranges_is_permutation.h +++ b/libcxx/include/__algorithm/ranges_is_permutation.h @@ -56,7 +56,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_equivalence_relation, projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -74,7 +74,7 @@ struct __fn { class _Proj2 = identity, indirect_equivalence_relation, _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) diff --git a/libcxx/include/__algorithm/ranges_is_sorted.h b/libcxx/include/__algorithm/ranges_is_sorted.h index d71035d5aa1d..5b88d422b4b0 100644 --- a/libcxx/include/__algorithm/ranges_is_sorted.h +++ b/libcxx/include/__algorithm/ranges_is_sorted.h @@ -37,7 +37,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last; } @@ -45,7 +45,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __last = ranges::end(__range); return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last; diff --git a/libcxx/include/__algorithm/ranges_is_sorted_until.h b/libcxx/include/__algorithm/ranges_is_sorted_until.h index dcfb6a4e1813..54de530c8b2f 100644 --- a/libcxx/include/__algorithm/ranges_is_sorted_until.h +++ b/libcxx/include/__algorithm/ranges_is_sorted_until.h @@ -53,7 +53,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -61,7 +61,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_lexicographical_compare.h b/libcxx/include/__algorithm/ranges_lexicographical_compare.h index 90e96b546516..6d82017e302a 100644 --- a/libcxx/include/__algorithm/ranges_lexicographical_compare.h +++ b/libcxx/include/__algorithm/ranges_lexicographical_compare.h @@ -60,7 +60,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -78,7 +78,7 @@ struct __fn { class _Proj2 = identity, indirect_strict_weak_order, _Proj1>, projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __lexicographical_compare_impl( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_lower_bound.h b/libcxx/include/__algorithm/ranges_lower_bound.h index ab1f80e7ab77..0651147e0424 100644 --- a/libcxx/include/__algorithm/ranges_lower_bound.h +++ b/libcxx/include/__algorithm/ranges_lower_bound.h @@ -43,7 +43,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); } @@ -52,7 +52,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { return std::__lower_bound<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_max.h b/libcxx/include/__algorithm/ranges_max.h index c63656de5134..d0ee6f314b0c 100644 --- a/libcxx/include/__algorithm/ranges_max.h +++ b/libcxx/include/__algorithm/ranges_max.h @@ -41,7 +41,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Comp __comp = {}, @@ -52,7 +52,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); @@ -65,7 +65,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_max_element.h b/libcxx/include/__algorithm/ranges_max_element.h index 83adf49b61ad..c57730927116 100644 --- a/libcxx/include/__algorithm/ranges_max_element.h +++ b/libcxx/include/__algorithm/ranges_max_element.h @@ -38,7 +38,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); @@ -47,7 +47,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); diff --git a/libcxx/include/__algorithm/ranges_min.h b/libcxx/include/__algorithm/ranges_min.h index e8f97f2754ac..cc569d2a060c 100644 --- a/libcxx/include/__algorithm/ranges_min.h +++ b/libcxx/include/__algorithm/ranges_min.h @@ -40,7 +40,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Comp __comp = {}, @@ -51,7 +51,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); @@ -62,7 +62,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_min_element.h b/libcxx/include/__algorithm/ranges_min_element.h index 4b9cb76da578..588ef258e26f 100644 --- a/libcxx/include/__algorithm/ranges_min_element.h +++ b/libcxx/include/__algorithm/ranges_min_element.h @@ -52,7 +52,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(__first, __last, __comp, __proj); } @@ -60,7 +60,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } diff --git a/libcxx/include/__algorithm/ranges_minmax.h b/libcxx/include/__algorithm/ranges_minmax.h index ca5722523336..09cbefd91a8c 100644 --- a/libcxx/include/__algorithm/ranges_minmax.h +++ b/libcxx/include/__algorithm/ranges_minmax.h @@ -52,7 +52,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result operator()(_LIBCPP_LIFETIMEBOUND const _Type& __a, _LIBCPP_LIFETIMEBOUND const _Type& __b, _Comp __comp = {}, @@ -65,7 +65,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list has to contain at least one element"); @@ -77,7 +77,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Range>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/libcxx/include/__algorithm/ranges_minmax_element.h b/libcxx/include/__algorithm/ranges_minmax_element.h index 5132856ebcd5..4bf6d2404e46 100644 --- a/libcxx/include/__algorithm/ranges_minmax_element.h +++ b/libcxx/include/__algorithm/ranges_minmax_element.h @@ -46,7 +46,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj); return {__ret.first, __ret.second}; @@ -55,7 +55,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); return {__ret.first, __ret.second}; diff --git a/libcxx/include/__algorithm/ranges_mismatch.h b/libcxx/include/__algorithm/ranges_mismatch.h index d8a7dd43af09..c4bf0022a9bc 100644 --- a/libcxx/include/__algorithm/ranges_mismatch.h +++ b/libcxx/include/__algorithm/ranges_mismatch.h @@ -65,7 +65,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( _I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2); @@ -77,7 +77,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_R2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result, borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go( diff --git a/libcxx/include/__algorithm/ranges_none_of.h b/libcxx/include/__algorithm/ranges_none_of.h index 59bd87997d44..7df3c1829fcf 100644 --- a/libcxx/include/__algorithm/ranges_none_of.h +++ b/libcxx/include/__algorithm/ranges_none_of.h @@ -46,7 +46,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -54,7 +54,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_remove.h b/libcxx/include/__algorithm/ranges_remove.h index 315bed8fba77..17c3a2c5cd06 100644 --- a/libcxx/include/__algorithm/ranges_remove.h +++ b/libcxx/include/__algorithm/ranges_remove.h @@ -37,7 +37,7 @@ namespace __remove { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) -> bool { return __value == __other; }; return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); @@ -46,7 +46,7 @@ struct __fn { template requires permutable> && indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) -> bool { return __value == __other; }; return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); diff --git a/libcxx/include/__algorithm/ranges_remove_if.h b/libcxx/include/__algorithm/ranges_remove_if.h index 943dbdd73807..0ea5d9a01b88 100644 --- a/libcxx/include/__algorithm/ranges_remove_if.h +++ b/libcxx/include/__algorithm/ranges_remove_if.h @@ -59,7 +59,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -68,7 +68,7 @@ struct __fn { class _Proj = identity, indirect_unary_predicate, _Proj>> _Pred> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/__algorithm/ranges_search.h b/libcxx/include/__algorithm/ranges_search.h index ca2326e9ab27..55294c60631b 100644 --- a/libcxx/include/__algorithm/ranges_search.h +++ b/libcxx/include/__algorithm/ranges_search.h @@ -77,7 +77,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -94,7 +94,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __first1 = ranges::begin(__range1); if constexpr (sized_range<_Range2>) { diff --git a/libcxx/include/__algorithm/ranges_search_n.h b/libcxx/include/__algorithm/ranges_search_n.h index 4c1d73d8e6c3..56e12755b9bf 100644 --- a/libcxx/include/__algorithm/ranges_search_n.h +++ b/libcxx/include/__algorithm/ranges_search_n.h @@ -71,7 +71,7 @@ struct __fn { class _Pred = ranges::equal_to, class _Proj = identity> requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, @@ -83,7 +83,7 @@ struct __fn { template requires indirectly_comparable, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( _Range&& __range, range_difference_t<_Range> __count, const _Type& __value, _Pred __pred = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__range); diff --git a/libcxx/include/__algorithm/ranges_starts_with.h b/libcxx/include/__algorithm/ranges_starts_with.h index 7ba8af13a8d1..17084e4f2433 100644 --- a/libcxx/include/__algorithm/ranges_starts_with.h +++ b/libcxx/include/__algorithm/ranges_starts_with.h @@ -42,7 +42,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -67,7 +67,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { return __mismatch::__fn::__go( ranges::begin(__range1), diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h index 7340310eb36a..7a9b78432187 100644 --- a/libcxx/include/__algorithm/ranges_unique.h +++ b/libcxx/include/__algorithm/ranges_unique.h @@ -47,7 +47,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_equivalence_relation> _Comp = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); @@ -58,7 +58,7 @@ struct __fn { class _Proj = identity, indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique<_RangeAlgPolicy>( ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); diff --git a/libcxx/include/__algorithm/ranges_upper_bound.h b/libcxx/include/__algorithm/ranges_upper_bound.h index 7b571fb3448f..fa6fa7f70ed5 100644 --- a/libcxx/include/__algorithm/ranges_upper_bound.h +++ b/libcxx/include/__algorithm/ranges_upper_bound.h @@ -37,7 +37,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) -> bool { return !std::invoke(__comp, __rhs, __lhs); @@ -50,7 +50,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) -> bool { return !std::invoke(__comp, __rhs, __lhs); diff --git a/libcxx/include/__algorithm/remove.h b/libcxx/include/__algorithm/remove.h index 1498852c4361..fd01c23cb670 100644 --- a/libcxx/include/__algorithm/remove.h +++ b/libcxx/include/__algorithm/remove.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __first = std::find(__first, __last, __value); if (__first != __last) { diff --git a/libcxx/include/__algorithm/remove_if.h b/libcxx/include/__algorithm/remove_if.h index c77b78023f52..b14f3c0efa7e 100644 --- a/libcxx/include/__algorithm/remove_if.h +++ b/libcxx/include/__algorithm/remove_if.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __first = std::find_if<_ForwardIterator, _Predicate&>(__first, __last, __pred); if (__first != __last) { diff --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h index 8557c76f80c4..b82ca7809535 100644 --- a/libcxx/include/__algorithm/search.h +++ b/libcxx/include/__algorithm/search.h @@ -160,7 +160,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __searc } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -173,14 +173,14 @@ search(_ForwardIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::search(__first1, __last1, __first2, __last2, __equal_to()); } #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { return __s(__f, __l).first; } diff --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h index 12007fa7dea0..771647d3168a 100644 --- a/libcxx/include/__algorithm/search_n.h +++ b/libcxx/include/__algorithm/search_n.h @@ -136,7 +136,7 @@ __search_n_impl(_Iter1 __first, _Sent1 __last, _DiffT __count, const _Type& __va } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n( _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) { static_assert( __is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, "BinaryPredicate has to be callable"); @@ -145,7 +145,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) { return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to()); } diff --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h index 056373d06fe4..d597014596f2 100644 --- a/libcxx/include/__algorithm/unique.h +++ b/libcxx/include/__algorithm/unique.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unique template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { __first = std::__adjacent_find(__first, __last, __pred); if (__first != __last) { @@ -46,13 +46,13 @@ __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last) { return std::unique(__first, __last, __equal_to()); } diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h index 9c7d8fbcde07..c39dec2e8969 100644 --- a/libcxx/include/__algorithm/upper_bound.h +++ b/libcxx/include/__algorithm/upper_bound.h @@ -48,7 +48,7 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); return std::__upper_bound<_ClassicAlgPolicy>( @@ -56,7 +56,7 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::upper_bound(std::move(__first), std::move(__last), __value, __less<>()); } diff --git a/libcxx/include/__bit/bit_cast.h b/libcxx/include/__bit/bit_cast.h index 6298810f3733..cd0456738179 100644 --- a/libcxx/include/__bit/bit_cast.h +++ b/libcxx/include/__bit/bit_cast.h @@ -33,7 +33,7 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr _ToType __bit_cast(const _From template requires(sizeof(_ToType) == sizeof(_FromType) && is_trivially_copyable_v<_ToType> && is_trivially_copyable_v<_FromType>) -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { return __builtin_bit_cast(_ToType, __from); } diff --git a/libcxx/include/__bit/bit_ceil.h b/libcxx/include/__bit/bit_ceil.h index 77fa739503bc..cfd792dc2e2a 100644 --- a/libcxx/include/__bit/bit_ceil.h +++ b/libcxx/include/__bit/bit_ceil.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - std::__countl_zero((_Tp)(__t - 1u)); @@ -42,7 +42,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) no # if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { return std::__bit_ceil(__t); } diff --git a/libcxx/include/__bit/bit_floor.h b/libcxx/include/__bit/bit_floor.h index cf5cf5803ad6..133e369504e4 100644 --- a/libcxx/include/__bit/bit_floor.h +++ b/libcxx/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); } diff --git a/libcxx/include/__bit/bit_width.h b/libcxx/include/__bit/bit_width.h index a2020a01421e..853e481776f7 100644 --- a/libcxx/include/__bit/bit_width.h +++ b/libcxx/include/__bit/bit_width.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : std::__bit_log2(__t) + 1; } diff --git a/libcxx/include/__bit/byteswap.h b/libcxx/include/__bit/byteswap.h index 20045d6fd43c..6225ecf2f92d 100644 --- a/libcxx/include/__bit/byteswap.h +++ b/libcxx/include/__bit/byteswap.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { if constexpr (sizeof(_Tp) == 1) { return __val; } else if constexpr (sizeof(_Tp) == 2) { diff --git a/libcxx/include/__bit/countl.h b/libcxx/include/__bit/countl.h index 13df8d4e66c4..998a0b44c19d 100644 --- a/libcxx/include/__bit/countl.h +++ b/libcxx/include/__bit/countl.h @@ -95,12 +95,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/countr.h b/libcxx/include/__bit/countr.h index 724a0bc23801..9e92021fba35 100644 --- a/libcxx/include/__bit/countr.h +++ b/libcxx/include/__bit/countr.h @@ -66,12 +66,12 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __coun #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { return std::__countr_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/has_single_bit.h b/libcxx/include/__bit/has_single_bit.h index a4e178060a73..52f5853a1bc8 100644 --- a/libcxx/include/__bit/has_single_bit.h +++ b/libcxx/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { return __t != 0 && (((__t & (__t - 1)) == 0)); } diff --git a/libcxx/include/__bit/popcount.h b/libcxx/include/__bit/popcount.h index 37b3a3e1f3f2..5cf0a01d0733 100644 --- a/libcxx/include/__bit/popcount.h +++ b/libcxx/include/__bit/popcount.h @@ -41,7 +41,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned lo #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { # if __has_builtin(__builtin_popcountg) return __builtin_popcountg(__t); # else // __has_builtin(__builtin_popcountg) diff --git a/libcxx/include/__chrono/leap_second.h b/libcxx/include/__chrono/leap_second.h index 2bbf06364673..1a0e7f3107de 100644 --- a/libcxx/include/__chrono/leap_second.h +++ b/libcxx/include/__chrono/leap_second.h @@ -43,9 +43,9 @@ public: _LIBCPP_HIDE_FROM_ABI leap_second(const leap_second&) = default; _LIBCPP_HIDE_FROM_ABI leap_second& operator=(const leap_second&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; } private: sys_seconds __date_; diff --git a/libcxx/include/__chrono/time_zone.h b/libcxx/include/__chrono/time_zone.h index 799602c1cdba..91ddab8903fe 100644 --- a/libcxx/include/__chrono/time_zone.h +++ b/libcxx/include/__chrono/time_zone.h @@ -56,10 +56,10 @@ public: _LIBCPP_HIDE_FROM_ABI time_zone(time_zone&&) = default; _LIBCPP_HIDE_FROM_ABI time_zone& operator=(time_zone&&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); } template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const { return __get_info(chrono::time_point_cast(__time)); } @@ -73,12 +73,12 @@ private: unique_ptr<__impl> __impl_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool operator==(const time_zone& __x, const time_zone& __y) noexcept { return __x.name() == __y.name(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering operator<=>(const time_zone& __x, const time_zone& __y) noexcept { return __x.name() <=> __y.name(); } diff --git a/libcxx/include/__chrono/time_zone_link.h b/libcxx/include/__chrono/time_zone_link.h index f44137829a81..b2d365c5fd08 100644 --- a/libcxx/include/__chrono/time_zone_link.h +++ b/libcxx/include/__chrono/time_zone_link.h @@ -38,15 +38,15 @@ namespace chrono { class time_zone_link { public: - _LIBCPP_NODISCARD_EXT + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit time_zone_link(__private_constructor_tag, string_view __name, string_view __target) : __name_{__name}, __target_{__target} {} _LIBCPP_HIDE_FROM_ABI time_zone_link(time_zone_link&&) = default; _LIBCPP_HIDE_FROM_ABI time_zone_link& operator=(time_zone_link&&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name_; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view target() const noexcept { return __target_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view target() const noexcept { return __target_; } private: string __name_; @@ -56,12 +56,12 @@ private: string __target_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool operator==(const time_zone_link& __x, const time_zone_link& __y) noexcept { return __x.name() == __y.name(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering operator<=>(const time_zone_link& __x, const time_zone_link& __y) noexcept { return __x.name() <=> __y.name(); } diff --git a/libcxx/include/__chrono/tzdb.h b/libcxx/include/__chrono/tzdb.h index 12fe6ccb63f9..f731f8c318be 100644 --- a/libcxx/include/__chrono/tzdb.h +++ b/libcxx/include/__chrono/tzdb.h @@ -57,14 +57,14 @@ struct tzdb { return nullptr; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const { if (const time_zone* __result = __locate_zone(__name)) return __result; std::__throw_runtime_error("tzdb: requested time zone not found"); } - _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const { + [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const { return __current_zone(); } diff --git a/libcxx/include/__chrono/tzdb_list.h b/libcxx/include/__chrono/tzdb_list.h index ae27067dbf02..62db7e3d2e0b 100644 --- a/libcxx/include/__chrono/tzdb_list.h +++ b/libcxx/include/__chrono/tzdb_list.h @@ -53,15 +53,15 @@ public: using const_iterator = forward_list::const_iterator; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } _LIBCPP_HIDE_FROM_ABI const_iterator erase_after(const_iterator __p) { return __erase_after(__p); } - _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(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } - _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 const_iterator cbegin() const noexcept { return __cbegin(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __impl& __implementation() { return *__impl_; } @@ -79,24 +79,23 @@ private: __impl* __impl_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list(); +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list(); -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const tzdb& get_tzdb() { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const tzdb& get_tzdb() { return get_tzdb_list().front(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* -locate_zone(string_view __name) { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* locate_zone(string_view __name) { return get_tzdb().locate_zone(__name); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() { return get_tzdb().current_zone(); } _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb(); -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version(); +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version(); } // namespace chrono diff --git a/libcxx/include/__config b/libcxx/include/__config index 4f5c1476626d..97cdd020c55d 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1375,7 +1375,7 @@ typedef __char32_t char32_t; # define _LIBCPP_USING_IF_EXISTS # endif -# if __has_cpp_attribute(nodiscard) +# if __has_cpp_attribute(__nodiscard__) # define _LIBCPP_NODISCARD [[__nodiscard__]] # else // We can't use GCC's [[gnu::warn_unused_result]] and @@ -1384,20 +1384,6 @@ typedef __char32_t char32_t; # define _LIBCPP_NODISCARD # endif -// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not -// specified as such as an extension. -# if !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_EXT -# endif - -# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_AFTER_CXX17 -# endif - # if __has_attribute(__no_destroy__) # define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) # else diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 9ffc90ada5e7..89d319b4b19b 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -812,7 +812,7 @@ public: _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); } // query - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); } _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); } _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); } diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h index c7810140105a..d14b49aff149 100644 --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -66,14 +66,13 @@ using wformat_args = basic_format_args; # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { return std::__format_arg_store<_Context, _Args...>(__args...); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store -make_wformat_args(_Args&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store make_wformat_args(_Args&... __args) { return std::__format_arg_store(__args...); } # endif @@ -452,8 +451,7 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string -vformat(string_view __fmt, format_args __args) { +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { string __res; std::vformat_to(std::back_inserter(__res), __fmt, __args); return __res; @@ -463,7 +461,7 @@ vformat(string_view __fmt, format_args __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { wstring __res; std::vformat_to(std::back_inserter(__res), __fmt, __args); @@ -472,14 +470,14 @@ vformat(wstring_view __fmt, wformat_args __args) { # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_format_args(__args...)); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(wformat_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); } @@ -520,14 +518,14 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, } template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); } @@ -585,7 +583,7 @@ format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&& // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(locale __loc, string_view __fmt, format_args __args) { string __res; std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); @@ -596,7 +594,7 @@ vformat(locale __loc, string_view __fmt, format_args __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(locale __loc, wstring_view __fmt, wformat_args __args) { wstring __res; std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); @@ -605,14 +603,14 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) { # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); } @@ -658,14 +656,14 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ } template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); } diff --git a/libcxx/include/__functional/identity.h b/libcxx/include/__functional/identity.h index b7be367bd5ee..8468de3dae26 100644 --- a/libcxx/include/__functional/identity.h +++ b/libcxx/include/__functional/identity.h @@ -44,7 +44,7 @@ struct __is_identity > : true_type {}; struct identity { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { return std::forward<_Tp>(__t); } diff --git a/libcxx/include/__iterator/empty.h b/libcxx/include/__iterator/empty.h index 3ca0aff6be46..773f2776955b 100644 --- a/libcxx/include/__iterator/empty.h +++ b/libcxx/include/__iterator/empty.h @@ -23,18 +23,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr auto empty(const _Cont& __c) - _NOEXCEPT_(noexcept(__c.empty())) -> decltype(__c.empty()) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto +empty(const _Cont& __c) noexcept(noexcept(__c.empty())) -> decltype(__c.empty()) { return __c.empty(); } template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr bool empty(const _Tp (&)[_Sz]) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty(const _Tp (&)[_Sz]) noexcept { return false; } template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr bool empty(initializer_list<_Ep> __il) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } diff --git a/libcxx/include/__math/abs.h b/libcxx/include/__math/abs.h index 6004690f4c4f..ab82a2800f53 100644 --- a/libcxx/include/__math/abs.h +++ b/libcxx/include/__math/abs.h @@ -23,19 +23,19 @@ namespace __math { // fabs -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { return __builtin_fabs(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT { return __builtin_fabsl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double fabs(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double fabs(_A1 __x) _NOEXCEPT { return __builtin_fabs((double)__x); } diff --git a/libcxx/include/__math/copysign.h b/libcxx/include/__math/copysign.h index 2219297e8b8c..b38690bb581a 100644 --- a/libcxx/include/__math/copysign.h +++ b/libcxx/include/__math/copysign.h @@ -25,17 +25,16 @@ namespace __math { // copysign -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { return ::__builtin_copysignf(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { return ::__builtin_copysignl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type -copysign(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { return ::__builtin_copysign(__x, __y); } diff --git a/libcxx/include/__math/min_max.h b/libcxx/include/__math/min_max.h index 381b2af4a56c..c2c4f6b64560 100644 --- a/libcxx/include/__math/min_max.h +++ b/libcxx/include/__math/min_max.h @@ -25,21 +25,21 @@ namespace __math { // fmax -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { return __builtin_fmaxf(__x, __y); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { return __builtin_fmax(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT { return __builtin_fmaxl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); return __math::fmax((__result_type)__x, (__result_type)__y); @@ -47,21 +47,21 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>: // fmin -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT { return __builtin_fminf(__x, __y); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { return __builtin_fmin(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT { return __builtin_fminl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); return __math::fmin((__result_type)__x, (__result_type)__y); diff --git a/libcxx/include/__math/roots.h b/libcxx/include/__math/roots.h index faee688bc95b..359fd747cfbe 100644 --- a/libcxx/include/__math/roots.h +++ b/libcxx/include/__math/roots.h @@ -39,19 +39,19 @@ inline _LIBCPP_HIDE_FROM_ABI double sqrt(_A1 __x) _NOEXCEPT { // cbrt -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT { return __builtin_cbrtf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT { return __builtin_cbrtf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { return __builtin_cbrt(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT { return __builtin_cbrtl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double cbrt(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double cbrt(_A1 __x) _NOEXCEPT { return __builtin_cbrt((double)__x); } diff --git a/libcxx/include/__math/rounding_functions.h b/libcxx/include/__math/rounding_functions.h index 29e42fd80b00..33e6cbc37d60 100644 --- a/libcxx/include/__math/rounding_functions.h +++ b/libcxx/include/__math/rounding_functions.h @@ -26,37 +26,37 @@ namespace __math { // ceil -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT { return __builtin_ceilf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT { return __builtin_ceilf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { return __builtin_ceil(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT { return __builtin_ceill(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double ceil(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double ceil(_A1 __x) _NOEXCEPT { return __builtin_ceil((double)__x); } // floor -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT { return __builtin_floorf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT { return __builtin_floorf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { return __builtin_floor(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT { return __builtin_floorl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double floor(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double floor(_A1 __x) _NOEXCEPT { return __builtin_floor((double)__x); } @@ -126,21 +126,21 @@ inline _LIBCPP_HIDE_FROM_ABI long lround(_A1 __x) _NOEXCEPT { // nearbyint -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT { return __builtin_nearbyintf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { return __builtin_nearbyint(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT { return __builtin_nearbyintl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double nearbyint(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double nearbyint(_A1 __x) _NOEXCEPT { return __builtin_nearbyint((double)__x); } @@ -186,55 +186,55 @@ inline _LIBCPP_HIDE_FROM_ABI double nexttoward(_A1 __x, long double __y) _NOEXCE // rint -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { return __builtin_rint(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { return __builtin_rintl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double rint(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double rint(_A1 __x) _NOEXCEPT { return __builtin_rint((double)__x); } // round -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_round(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_round(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { return __builtin_round(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { return __builtin_roundl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double round(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double round(_A1 __x) _NOEXCEPT { return __builtin_round((double)__x); } // trunc -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_trunc(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_trunc(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { return __builtin_trunc(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { return __builtin_truncl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double trunc(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double trunc(_A1 __x) _NOEXCEPT { return __builtin_trunc((double)__x); } diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index da585af8837f..a44826679755 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -29,55 +29,55 @@ namespace __math { // signbit template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __builtin_signbit(__x); } template ::value && is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } template ::value && !is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { return false; } // isfinite template ::value && numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { return __builtin_isfinite((typename __promote<_A1>::type)__x); } template ::value && !numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { return true; } // isinf template ::value && numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { return __builtin_isinf((typename __promote<_A1>::type)__x); } template ::value && !numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { return false; } #ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { return __builtin_isinf(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT { return __builtin_isinf(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { return __builtin_isinf(__x); } #endif @@ -85,26 +85,26 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI // isnan template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { return __builtin_isnan(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { return false; } #ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { return __builtin_isnan(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT { return __builtin_isnan(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { return __builtin_isnan(__x); } #endif @@ -112,19 +112,19 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI // isnormal template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __builtin_isnormal(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __x != 0; } // isgreater template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isgreater((type)__x, (type)__y); } @@ -132,7 +132,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 _ // isgreaterequal template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isgreaterequal((type)__x, (type)__y); } @@ -140,7 +140,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, // isless template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isless((type)__x, (type)__y); } @@ -148,7 +148,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) // islessequal template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_islessequal((type)__x, (type)__y); } @@ -156,7 +156,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 // islessgreater template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_islessgreater((type)__x, (type)__y); } @@ -164,7 +164,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _ // isunordered template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isunordered((type)__x, (type)__y); } diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h index 26e5d4978b15..215d3832f9ef 100644 --- a/libcxx/include/__memory/allocator.h +++ b/libcxx/include/__memory/allocator.h @@ -110,7 +110,7 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { @@ -153,8 +153,7 @@ public: return std::addressof(__x); } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 _Tp* - allocate(size_t __n, const void*) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 _Tp* allocate(size_t __n, const void*) { return allocate(__n); } @@ -190,7 +189,7 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const _Tp* allocate(size_t __n) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { @@ -230,8 +229,7 @@ public: return std::addressof(__x); } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 const _Tp* - allocate(size_t __n, const void*) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 const _Tp* allocate(size_t __n, const void*) { return allocate(__n); } diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index 7b3deb0f58e9..47fe132d15cb 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -275,13 +275,13 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits { }; #endif // _LIBCPP_CXX03_LANG - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n) { return __a.allocate(__n); } template ::value, int> = 0> - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) { _LIBCPP_SUPPRESS_DEPRECATED_PUSH return __a.allocate(__n, __hint); @@ -290,7 +290,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits { template ::value, int> = 0> - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer) { return __a.allocate(__n); } diff --git a/libcxx/include/__memory/temporary_buffer.h b/libcxx/include/__memory/temporary_buffer.h index e3797caff8c9..88799ca95c1f 100644 --- a/libcxx/include/__memory/temporary_buffer.h +++ b/libcxx/include/__memory/temporary_buffer.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t> get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT { pair<_Tp*, ptrdiff_t> __r(0, 0); const ptrdiff_t __m = diff --git a/libcxx/include/__memory_resource/memory_resource.h b/libcxx/include/__memory_resource/memory_resource.h index 418f36dc9b39..e605838bf5ea 100644 --- a/libcxx/include/__memory_resource/memory_resource.h +++ b/libcxx/include/__memory_resource/memory_resource.h @@ -32,9 +32,8 @@ class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource { public: virtual ~memory_resource(); - _LIBCPP_NODISCARD_AFTER_CXX17 - [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void* - allocate(size_t __bytes, size_t __align = __max_align) { + [[nodiscard]] [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] + _LIBCPP_HIDE_FROM_ABI void* allocate(size_t __bytes, size_t __align = __max_align) { return do_allocate(__bytes, __align); } diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h index 823c1503c22b..8fda20112438 100644 --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -61,7 +61,7 @@ public: // [mem.poly.allocator.mem] - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { if (__n > __max_size()) { __throw_bad_array_new_length(); } diff --git a/libcxx/include/__mutex/lock_guard.h b/libcxx/include/__mutex/lock_guard.h index c075512fb97a..739d1683b317 100644 --- a/libcxx/include/__mutex/lock_guard.h +++ b/libcxx/include/__mutex/lock_guard.h @@ -29,13 +29,13 @@ private: mutex_type& __m_; public: - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) - _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + _LIBCPP_NODISCARD + _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) { __m_.lock(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index 24d2624c3739..d0b35bfd1934 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -147,7 +147,7 @@ public: _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) { diff --git a/libcxx/include/__ranges/as_rvalue_view.h b/libcxx/include/__ranges/as_rvalue_view.h index 2fc272e798d6..5849a6c36839 100644 --- a/libcxx/include/__ranges/as_rvalue_view.h +++ b/libcxx/include/__ranges/as_rvalue_view.h @@ -111,7 +111,7 @@ namespace views { namespace __as_rvalue { struct __fn : __range_adaptor_closure<__fn> { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range) noexcept(noexcept(as_rvalue_view(std::forward<_Range>(__range)))) -> decltype(/*--------------------------*/ as_rvalue_view(std::forward<_Range>(__range))) { return /*---------------------------------*/ as_rvalue_view(std::forward<_Range>(__range)); @@ -119,7 +119,7 @@ struct __fn : __range_adaptor_closure<__fn> { template requires same_as, range_reference_t<_Range>> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range) noexcept(noexcept(views::all(std::forward<_Range>(__range)))) -> decltype(/*--------------------------*/ views::all(std::forward<_Range>(__range))) { return /*---------------------------------*/ views::all(std::forward<_Range>(__range)); diff --git a/libcxx/include/__ranges/chunk_by_view.h b/libcxx/include/__ranges/chunk_by_view.h index b04a23de99fb..00014d9f10ae 100644 --- a/libcxx/include/__ranges/chunk_by_view.h +++ b/libcxx/include/__ranges/chunk_by_view.h @@ -205,7 +205,7 @@ namespace views { namespace __chunk_by { struct __fn { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const noexcept(noexcept(/**/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)))) -> decltype(/*--*/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) { return /*-------------*/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)); @@ -213,7 +213,7 @@ struct __fn { template requires constructible_from, _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const noexcept(is_nothrow_constructible_v, _Pred>) { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred))); } diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h index 83bb598b0a0c..fbfbca4db621 100644 --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -266,7 +266,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires (__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept(views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) -> decltype( views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { return views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } @@ -277,7 +277,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires (__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&&) const noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) diff --git a/libcxx/include/__ranges/repeat_view.h b/libcxx/include/__ranges/repeat_view.h index 5caea757a393..0941770f0eef 100644 --- a/libcxx/include/__ranges/repeat_view.h +++ b/libcxx/include/__ranges/repeat_view.h @@ -229,13 +229,13 @@ namespace views { namespace __repeat { struct __fn { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) -> decltype( ranges::repeat_view(std::forward<_Tp>(__value))) { return ranges::repeat_view(std::forward<_Tp>(__value)); } template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h index 98f17be04f62..ce3606aedfef 100644 --- a/libcxx/include/__ranges/split_view.h +++ b/libcxx/include/__ranges/split_view.h @@ -200,7 +200,7 @@ namespace __split_view { struct __fn { // clang-format off template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const noexcept(noexcept(split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) -> decltype( split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) @@ -209,7 +209,7 @@ struct __fn { template requires constructible_from, _Pattern> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const noexcept(is_nothrow_constructible_v, _Pattern>) { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); } diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h index 83ed5ca0ebd3..27ca8155a69b 100644 --- a/libcxx/include/__ranges/take_view.h +++ b/libcxx/include/__ranges/take_view.h @@ -308,7 +308,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires(__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept(views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) -> decltype( views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { return views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } @@ -319,7 +319,7 @@ struct __fn { class _RawRange = remove_cvref_t<_Range>, class _Dist = range_difference_t<_Range>> requires(__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept(views::repeat(*__range.__value_, static_cast<_Dist>(__n)))) -> decltype( views::repeat(*__range.__value_, static_cast<_Dist>(__n))) { return views::repeat(*__range.__value_, static_cast<_Dist>(__n)); } diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h index 67818c521b15..8a815bce5811 100644 --- a/libcxx/include/__ranges/to.h +++ b/libcxx/include/__ranges/to.h @@ -85,7 +85,7 @@ concept __always_false = false; // `ranges::to` base template -- the `_Container` type is a simple type template parameter. template requires(!view<_Container>) -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Container to(_Range&& __range, _Args&&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Container to(_Range&& __range, _Args&&... __args) { // Mandates: C is a cv-unqualified class type. static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const"); static_assert( @@ -192,7 +192,7 @@ struct _Deducer { // `ranges::to` specialization -- `_Container` is a template template parameter requiring deduction to figure out the // container element type. template