From 20e0bacd0560382a31ad0d4ecc7472bd4a99c659 Mon Sep 17 00:00:00 2001
From: Joseph Huber
Date: Fri, 22 Mar 2024 19:08:47 -0500
Subject: [PATCH 001/879] [Libomptarget][Fix] Remove duplicate version script
for host builds
Summary:
This causes an error on some linkers and was mistakenly kept in.
---
openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt | 5 -----
1 file changed, 5 deletions(-)
diff --git a/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt
index d30680e10431..ccbf7d033fd6 100644
--- a/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt
+++ b/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt
@@ -31,11 +31,6 @@ else()
target_include_directories(omptarget.rtl.${machine} PRIVATE dynamic_ffi)
endif()
-if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
- target_link_libraries(omptarget.rtl.${machine} PRIVATE
- "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports")
-endif()
-
# Install plugin under the lib destination folder.
install(TARGETS omptarget.rtl.${machine}
LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}")
--
GitLab
From dc43aa439ecee90a9f51c6c1e46df8be61e0457c Mon Sep 17 00:00:00 2001
From: Charlie Barto
Date: Fri, 22 Mar 2024 17:38:34 -0700
Subject: [PATCH 002/879] [asan][windows] When compiling with clang-cl or MSVC
pass /Zl (that's a little L) (#85874)
/Zl is the equivalent of -nodefaultlibs. The idea here is to make sure
that the asan runtime doesn't have any defaultlibs directives, which
makes it easier to mix an asan runtime built with the dynamic CRT with
an application built with the static CRT (or vise-versa).
This is part of the overall effort to remove the static asan runtime on
windows entirely: https://github.com/llvm/llvm-project/pull/81677
Co-authored-by: Amy Wishnousky
---
compiler-rt/lib/asan/CMakeLists.txt | 3 +++
compiler-rt/lib/sanitizer_common/CMakeLists.txt | 2 ++
compiler-rt/lib/ubsan/CMakeLists.txt | 1 +
3 files changed, 6 insertions(+)
diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index f83ae82d4293..601750f72175 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -85,6 +85,9 @@ SET(ASAN_HEADERS
include_directories(..)
set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+
+append_list_if(MSVC /Zl ASAN_CFLAGS)
+
set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION})
append_rtti_flag(OFF ASAN_CFLAGS)
diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
index f762524c333a..f2b4ac72ae15 100644
--- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
@@ -218,6 +218,8 @@ include_directories(..)
set(SANITIZER_COMMON_DEFINITIONS
HAVE_RPC_XDR_H=${HAVE_RPC_XDR_H})
+# note: L not I, this is nodefaultlibs for msvc
+append_list_if(MSVC /Zl SANITIZER_COMMON_CFLAGS)
set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS})
# Too many existing bugs, needs cleanup.
diff --git a/compiler-rt/lib/ubsan/CMakeLists.txt b/compiler-rt/lib/ubsan/CMakeLists.txt
index 3f1e12ed9ac6..db0b33f1276e 100644
--- a/compiler-rt/lib/ubsan/CMakeLists.txt
+++ b/compiler-rt/lib/ubsan/CMakeLists.txt
@@ -41,6 +41,7 @@ set(UBSAN_HEADERS
include_directories(..)
set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+append_list_if(MSVC /Zl UBSAN_CFLAGS)
append_rtti_flag(OFF UBSAN_CFLAGS)
append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CFLAGS)
--
GitLab
From b723c57f8fdb12ca8eaa6c5ee2afb820aaeb56c5 Mon Sep 17 00:00:00 2001
From: Corentin Jabot
Date: Sat, 23 Mar 2024 09:28:33 +0900
Subject: [PATCH 003/879] [Clang] Update the C++ page with papers approved in
Tokyo
---
clang/www/cxx_status.html | 42 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 1e36b90356c3..c1d95dadbb27 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -163,7 +163,47 @@ C++23, informally referred to as C++26.
P2864R2 |
Clang 18 |
-
+
+
+ | Disallow Binding a Returned Glvalue to a Temporary |
+ P2748R5 |
+ No |
+
+
+ | Clarifying rules for brace elision in aggregate initialization |
+ P3106R1 (DR) |
+ No |
+
+
+ | Attributes for Structured Bindings |
+ P0609R3 |
+ No |
+
+
+ | Module Declarations Shouldn’t be Macros |
+ P3034R1 (DR) |
+ No |
+
+
+ | Trivial infinite loops are not Undefined Behavior |
+ P2809R3 (DR) |
+ No |
+
+
+ | Erroneous behaviour for uninitialized reads |
+ P2795R5 |
+ No |
+
+
+ | = delete("should have a reason"); |
+ P2573R2 |
+ No |
+
+
+ | Variadic friends |
+ P2893R3 |
+ No |
+
--
GitLab
From 2f6b1b4b30e3a719b1744baa4cd1ece504998c6e Mon Sep 17 00:00:00 2001
From: Keith Smiley
Date: Fri, 22 Mar 2024 18:10:21 -0700
Subject: [PATCH 004/879] [ORC] Add default visibility to required JIT
functions (#86322)
If you build LLVM with `-DCMAKE_CXX_VISIBILITY_PRESET=hidden` to help
reduce binary size, these symbols end up becoming local, and getting
stripped. This forces default visibility to override the global setting
in that case.
Relevant:
https://github.com/llvm/llvm-project/issues/62815#issuecomment-1560078260
---
llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
index 8a4145a6b02a..7529d9cef67e 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
@@ -26,11 +26,13 @@ extern "C" {
// We put information about the JITed function in this global, which the
// debugger reads. Make sure to specify the version statically, because the
// debugger checks the version before we can set it during runtime.
+LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
struct jit_descriptor __jit_debug_descriptor = {JitDescriptorVersion, 0,
nullptr, nullptr};
// Debuggers that implement the GDB JIT interface put a special breakpoint in
// this function.
+LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
// The noinline and the asm prevent calls to this function from being
// optimized out.
--
GitLab
From 84e20cb0cbc64bb2d8299b30da3ce8e6421c203e Mon Sep 17 00:00:00 2001
From: Craig Topper
Date: Fri, 22 Mar 2024 16:56:48 -0700
Subject: [PATCH 005/879] [TableGen] Minor cleanup in
CodeGenRegBank::getConcatSubRegIndex. NFC
Mark a variable const. Capitalize a variable name.
I'm going to add HwMode support to this code and wanted to clean it
up a bit beforehand.
---
llvm/utils/TableGen/CodeGenRegisters.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp
index 40af0d3077b2..e851d4c16bf7 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -1400,11 +1400,11 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
// None exists, synthesize one.
std::string Name = Parts.front()->getName();
// Determine whether all parts are contiguous.
- bool isContinuous = true;
+ bool IsContinuous = true;
unsigned Size = Parts.front()->Size;
unsigned LastOffset = Parts.front()->Offset;
unsigned LastSize = Parts.front()->Size;
- unsigned UnknownSize = (uint16_t)-1;
+ const unsigned UnknownSize = (uint16_t)-1;
for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
Name += '_';
Name += Parts[i]->getName();
@@ -1413,13 +1413,13 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
else
Size += Parts[i]->Size;
if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize))
- isContinuous = false;
+ IsContinuous = false;
LastOffset = Parts[i]->Offset;
LastSize = Parts[i]->Size;
}
Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
Idx->Size = Size;
- Idx->Offset = isContinuous ? Parts.front()->Offset : -1;
+ Idx->Offset = IsContinuous ? Parts.front()->Offset : -1;
Idx->ConcatenationOf.assign(Parts.begin(), Parts.end());
return Idx;
}
--
GitLab
From 76fdb5902fbadbc08c6742156071431d8ad801ea Mon Sep 17 00:00:00 2001
From: paperchalice
Date: Sat, 23 Mar 2024 10:37:53 +0800
Subject: [PATCH 006/879] [NewPM][DirectX] Add DirectXPassRegistry.def NFCI
(#86242)
Prepare migration for dag-isel
---
.../Target/DirectX/DirectXPassRegistry.def | 29 +++++++++++++++++++
.../Target/DirectX/DirectXTargetMachine.cpp | 20 ++-----------
2 files changed, 31 insertions(+), 18 deletions(-)
create mode 100644 llvm/lib/Target/DirectX/DirectXPassRegistry.def
diff --git a/llvm/lib/Target/DirectX/DirectXPassRegistry.def b/llvm/lib/Target/DirectX/DirectXPassRegistry.def
new file mode 100644
index 000000000000..bbf0c254bb69
--- /dev/null
+++ b/llvm/lib/Target/DirectX/DirectXPassRegistry.def
@@ -0,0 +1,29 @@
+//===- DirectXPassRegistry.def - Registry of DirectX 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is used as the registry of passes that are part of the
+// DirectX backend.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef MODULE_ANALYSIS
+#define MODULE_ANALYSIS(NAME, CREATE_PASS)
+#endif
+MODULE_ANALYSIS("dx-shader-flags", dxil::ShaderFlagsAnalysis())
+MODULE_ANALYSIS("dxil-resource", DXILResourceAnalysis())
+#undef MODULE_ANALYSIS
+
+#ifndef MODULE_PASS
+#define MODULE_PASS(NAME, CREATE_PASS)
+#endif
+// TODO: rename to print after NPM switch
+MODULE_PASS("print-dx-shader-flags", DXILResourcePrinterPass(dbgs()))
+MODULE_PASS("print-dxil-resource", DXILResourcePrinterPass(dbgs()))
+#undef MODULE_PASS
diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
index 03c825b3977d..bebca0675522 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
@@ -104,24 +104,8 @@ DirectXTargetMachine::~DirectXTargetMachine() {}
void DirectXTargetMachine::registerPassBuilderCallbacks(
PassBuilder &PB, bool PopulateClassToPassNames) {
- PB.registerPipelineParsingCallback(
- [](StringRef PassName, ModulePassManager &PM,
- ArrayRef) {
- if (PassName == "print-dxil-resource") {
- PM.addPass(DXILResourcePrinterPass(dbgs()));
- return true;
- }
- if (PassName == "print-dx-shader-flags") {
- PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs()));
- return true;
- }
- return false;
- });
-
- PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) {
- MAM.registerPass([&] { return DXILResourceAnalysis(); });
- MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); });
- });
+#define GET_PASS_REGISTRY "DirectXPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
}
bool DirectXTargetMachine::addPassesToEmitFile(
--
GitLab
From 7ac7d418ac2b16fd44789dcf48e2b5d73de3e715 Mon Sep 17 00:00:00 2001
From: paperchalice
Date: Sat, 23 Mar 2024 11:20:18 +0800
Subject: [PATCH 007/879] [NewPM][NVPTX] Add NVPTXPassRegistry.def NFCI
(#86246)
Prepare for dag-isel migration.
---
llvm/lib/Target/NVPTX/NVPTXPassRegistry.def | 40 +++++++++++++++++++
llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp | 41 +-------------------
2 files changed, 42 insertions(+), 39 deletions(-)
create mode 100644 llvm/lib/Target/NVPTX/NVPTXPassRegistry.def
diff --git a/llvm/lib/Target/NVPTX/NVPTXPassRegistry.def b/llvm/lib/Target/NVPTX/NVPTXPassRegistry.def
new file mode 100644
index 000000000000..6ff15ab6f13c
--- /dev/null
+++ b/llvm/lib/Target/NVPTX/NVPTXPassRegistry.def
@@ -0,0 +1,40 @@
+//===- NVPTXPassRegistry.def - Registry of NVPTX 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is used as the registry of passes that are part of the
+// NVPTX backend.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef MODULE_PASS
+#define MODULE_PASS(NAME, CREATE_PASS)
+#endif
+MODULE_PASS("generic-to-nvvm", GenericToNVVMPass())
+MODULE_PASS("nvptx-lower-ctor-dtor", NVPTXCtorDtorLoweringPass())
+#undef MODULE_PASS
+
+#ifndef FUNCTION_ANALYSIS
+#define FUNCTION_ANALYSIS(NAME, CREATE_PASS)
+#endif
+
+#ifndef FUNCTION_ALIAS_ANALYSIS
+#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
+ FUNCTION_ANALYSIS(NAME, CREATE_PASS)
+#endif
+FUNCTION_ALIAS_ANALYSIS("nvptx-aa", NVPTXAA())
+#undef FUNCTION_ALIAS_ANALYSIS
+#undef FUNCTION_ANALYSIS
+
+#ifndef FUNCTION_PASS
+#define FUNCTION_PASS(NAME, CREATE_PASS)
+#endif
+FUNCTION_PASS("nvvm-intr-range", NVVMIntrRangePass())
+FUNCTION_PASS("nvvm-reflect", NVVMReflectPass())
+#undef FUNCTION_PASS
diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp
index 69d4596f7843..78f48652c992 100644
--- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp
@@ -227,45 +227,8 @@ void NVPTXTargetMachine::registerDefaultAliasAnalyses(AAManager &AAM) {
void NVPTXTargetMachine::registerPassBuilderCallbacks(
PassBuilder &PB, bool PopulateClassToPassNames) {
- PB.registerPipelineParsingCallback(
- [](StringRef PassName, FunctionPassManager &PM,
- ArrayRef) {
- if (PassName == "nvvm-reflect") {
- PM.addPass(NVVMReflectPass());
- return true;
- }
- if (PassName == "nvvm-intr-range") {
- PM.addPass(NVVMIntrRangePass());
- return true;
- }
- return false;
- });
-
- PB.registerAnalysisRegistrationCallback([](FunctionAnalysisManager &FAM) {
- FAM.registerPass([&] { return NVPTXAA(); });
- });
-
- PB.registerParseAACallback([](StringRef AAName, AAManager &AAM) {
- if (AAName == "nvptx-aa") {
- AAM.registerFunctionAnalysis();
- return true;
- }
- return false;
- });
-
- PB.registerPipelineParsingCallback(
- [](StringRef PassName, ModulePassManager &PM,
- ArrayRef) {
- if (PassName == "nvptx-lower-ctor-dtor") {
- PM.addPass(NVPTXCtorDtorLoweringPass());
- return true;
- }
- if (PassName == "generic-to-nvvm") {
- PM.addPass(GenericToNVVMPass());
- return true;
- }
- return false;
- });
+#define GET_PASS_REGISTRY "NVPTXPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
PB.registerPipelineStartEPCallback(
[this](ModulePassManager &PM, OptimizationLevel Level) {
--
GitLab
From 2aa5bae0c03f1f857d0ae2a881b223c4a521853f Mon Sep 17 00:00:00 2001
From: paperchalice
Date: Sat, 23 Mar 2024 12:53:26 +0800
Subject: [PATCH 008/879] [NewPM][BPF] Add BPFPassRegistry.def NFCI (#86241)
Prepare migration for dag-isel.
---
llvm/lib/Target/BPF/BPFPassRegistry.def | 32 ++++++++++++++++++++++++
llvm/lib/Target/BPF/BPFTargetMachine.cpp | 25 ++++++------------
2 files changed, 40 insertions(+), 17 deletions(-)
create mode 100644 llvm/lib/Target/BPF/BPFPassRegistry.def
diff --git a/llvm/lib/Target/BPF/BPFPassRegistry.def b/llvm/lib/Target/BPF/BPFPassRegistry.def
new file mode 100644
index 000000000000..73a8ef2f95bf
--- /dev/null
+++ b/llvm/lib/Target/BPF/BPFPassRegistry.def
@@ -0,0 +1,32 @@
+//===- BPFPassRegistry.def - Registry of BPF 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is used as the registry of passes that are part of the
+// BPF backend.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef FUNCTION_PASS
+#define FUNCTION_PASS(NAME, CREATE_PASS)
+#endif
+FUNCTION_PASS("bpf-aspace-simplify", BPFASpaceCastSimplifyPass())
+FUNCTION_PASS("bpf-ir-peephole", BPFIRPeepholePass())
+#undef FUNCTION_PASS
+
+#ifndef FUNCTION_PASS_WITH_PARAMS
+#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS)
+#endif
+FUNCTION_PASS_WITH_PARAMS(
+ "bpf-preserve-static-offset", "BPFPreserveStaticOffsetPass",
+ [=](bool AllowPartial) {
+ return BPFPreserveStaticOffsetPass(AllowPartial);
+ },
+ parseBPFPreserveStaticOffsetOptions, "allow-partial")
+#undef FUNCTION_PASS_WITH_PARAMS
diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
index 5f26bec2e390..a7bed69b0f2a 100644
--- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
@@ -108,25 +108,16 @@ TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) {
return new BPFPassConfig(*this, PM);
}
+static Expected parseBPFPreserveStaticOffsetOptions(StringRef Params) {
+ return PassBuilder::parseSinglePassOption(Params, "allow-partial",
+ "BPFPreserveStaticOffsetPass");
+}
+
void BPFTargetMachine::registerPassBuilderCallbacks(
PassBuilder &PB, bool PopulateClassToPassNames) {
- PB.registerPipelineParsingCallback(
- [](StringRef PassName, FunctionPassManager &FPM,
- ArrayRef) {
- if (PassName == "bpf-ir-peephole") {
- FPM.addPass(BPFIRPeepholePass());
- return true;
- }
- if (PassName == "bpf-preserve-static-offset") {
- FPM.addPass(BPFPreserveStaticOffsetPass(false));
- return true;
- }
- if (PassName == "bpf-aspace-simplify") {
- FPM.addPass(BPFASpaceCastSimplifyPass());
- return true;
- }
- return false;
- });
+#define GET_PASS_REGISTRY "BPFPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
+
PB.registerPipelineStartEPCallback(
[=](ModulePassManager &MPM, OptimizationLevel) {
FunctionPassManager FPM;
--
GitLab
From 635ea257eca7c8e95c6ea30ca3816a0b5584ab37 Mon Sep 17 00:00:00 2001
From: paperchalice
Date: Sat, 23 Mar 2024 13:06:58 +0800
Subject: [PATCH 009/879] [NewPM] Fix BPF build (#86379)
Add Passes in dependency list
---
llvm/lib/Target/BPF/CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt
index cb21ed03a86c..eade4cacb710 100644
--- a/llvm/lib/Target/BPF/CMakeLists.txt
+++ b/llvm/lib/Target/BPF/CMakeLists.txt
@@ -54,6 +54,7 @@ add_llvm_target(BPFCodeGen
GlobalISel
IPO
MC
+ Passes
Scalar
SelectionDAG
Support
--
GitLab
From 6c1932ffd82e733325180fe13ef46b24ff606eab Mon Sep 17 00:00:00 2001
From: Yingwei Zheng
Date: Sat, 23 Mar 2024 14:57:35 +0800
Subject: [PATCH 010/879] [LLVM] Pass APInt by const reference. NFC. (#86278)
This patch adjusts argument passing for `APInt` to improve the
compile-time.
Compile-time improvement:
https://llvm-compile-time-tracker.com/compare.php?from=d1f182c895728d89c5c3d198b133e212a5d9d4a3&to=32d6611af69bf4e76373f9bc7d9649650f760e48&stat=instructions:u
---
llvm/include/llvm/Analysis/MemoryBuiltins.h | 2 +-
llvm/include/llvm/CodeGen/SelectionDAG.h | 2 +-
llvm/include/llvm/MC/MCStreamer.h | 2 +-
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 2 +-
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 ++-
llvm/lib/MC/MCStreamer.cpp | 2 +-
6 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index 37ce1518f00c..da092866de65 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -217,7 +217,7 @@ struct SizeOffsetAPInt : public SizeOffsetType {
SizeOffsetAPInt() = default;
SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {}
- static bool known(APInt V) { return V.getBitWidth() > 1; }
+ static bool known(const APInt &V) { return V.getBitWidth() > 1; }
};
/// Evaluate the size and offset of an object pointed to by a Value*
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 4785e93d72d1..574c63552ce0 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -883,7 +883,7 @@ public:
/// Returns a vector of type ResVT whose elements contain the linear sequence
/// <0, Step, Step * 2, Step * 3, ...>
- SDValue getStepVector(const SDLoc &DL, EVT ResVT, APInt StepVal);
+ SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal);
/// Returns a vector of type ResVT whose elements contain the linear sequence
/// <0, 1, 2, 3, ...>
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 671511ab4b88..69867620e1bf 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -740,7 +740,7 @@ public:
/// Special case of EmitValue that avoids the client having
/// to pass in a MCExpr for constant integers.
virtual void emitIntValue(uint64_t Value, unsigned Size);
- virtual void emitIntValue(APInt Value);
+ virtual void emitIntValue(const APInt &Value);
/// Special case of EmitValue that avoids the client having to pass
/// in a MCExpr for constant integers & prints in Hex format for certain
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 8d608f6ac5e4..1b25da8833e4 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -7855,7 +7855,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerBswap(MachineInstr &MI) {
//{ (Src & Mask) >> N } | { (Src << N) & Mask }
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B,
- MachineInstrBuilder Src, APInt Mask) {
+ MachineInstrBuilder Src, const APInt &Mask) {
const LLT Ty = Dst.getLLTTy(*B.getMRI());
MachineInstrBuilder C_N = B.buildConstant(Ty, N);
MachineInstrBuilder MaskLoNTo0 = B.buildConstant(Ty, Mask);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index cd6f083243d0..e2c07e7cb997 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2031,7 +2031,8 @@ SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT) {
return getStepVector(DL, ResVT, One);
}
-SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT, APInt StepVal) {
+SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT,
+ const APInt &StepVal) {
assert(ResVT.getScalarSizeInBits() == StepVal.getBitWidth());
if (ResVT.isScalableVector())
return getNode(
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index d0395770ae8b..176d55aa890b 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -141,7 +141,7 @@ void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) {
unsigned Index = IsLittleEndian ? 0 : 8 - Size;
emitBytes(StringRef(reinterpret_cast(&Swapped) + Index, Size));
}
-void MCStreamer::emitIntValue(APInt Value) {
+void MCStreamer::emitIntValue(const APInt &Value) {
if (Value.getNumWords() == 1) {
emitIntValue(Value.getLimitedValue(), Value.getBitWidth() / 8);
return;
--
GitLab
From 2f1f6b704d83f87be7ea885480caf1c86d8cfaee Mon Sep 17 00:00:00 2001
From: Yingwei Zheng
Date: Sat, 23 Mar 2024 14:58:25 +0800
Subject: [PATCH 011/879] [LLVM] Use `std::move` for APInt. NFC. (#86257)
This patch adjusts argument passing for `APInt` to improve the
compile-time.
Compile-time improvement:
https://llvm-compile-time-tracker.com/compare.php?from=d1f182c895728d89c5c3d198b133e212a5d9d4a3&to=ba3e326def3a6e5cd6d72ff5a49c74fba18de1df&stat=instructions:u
---
llvm/include/llvm/Analysis/InlineCost.h | 3 ++-
llvm/include/llvm/Analysis/MemoryBuiltins.h | 6 ++++--
llvm/lib/Analysis/ConstantFolding.cpp | 2 +-
llvm/lib/Analysis/InstructionSimplify.cpp | 6 ++++--
llvm/lib/IR/LLVMContextImpl.h | 2 +-
llvm/lib/Transforms/Scalar/MergeICmps.cpp | 2 +-
6 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Analysis/InlineCost.h b/llvm/include/llvm/Analysis/InlineCost.h
index 3a760e0a85ce..c5978ce54fc1 100644
--- a/llvm/include/llvm/Analysis/InlineCost.h
+++ b/llvm/include/llvm/Analysis/InlineCost.h
@@ -65,7 +65,8 @@ const char MaxInlineStackSizeAttributeName[] = "inline-max-stacksize";
// The cost-benefit pair computed by cost-benefit analysis.
class CostBenefitPair {
public:
- CostBenefitPair(APInt Cost, APInt Benefit) : Cost(Cost), Benefit(Benefit) {}
+ CostBenefitPair(APInt Cost, APInt Benefit)
+ : Cost(std::move(Cost)), Benefit(std::move(Benefit)) {}
const APInt &getCost() const { return Cost; }
diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index da092866de65..bb282a1b73d3 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -196,7 +196,8 @@ public:
T Offset;
SizeOffsetType() = default;
- SizeOffsetType(T Size, T Offset) : Size(Size), Offset(Offset) {}
+ SizeOffsetType(T Size, T Offset)
+ : Size(std::move(Size)), Offset(std::move(Offset)) {}
bool knownSize() const { return C::known(Size); }
bool knownOffset() const { return C::known(Offset); }
@@ -215,7 +216,8 @@ public:
/// \p APInts.
struct SizeOffsetAPInt : public SizeOffsetType {
SizeOffsetAPInt() = default;
- SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {}
+ SizeOffsetAPInt(APInt Size, APInt Offset)
+ : SizeOffsetType(std::move(Size), std::move(Offset)) {}
static bool known(const APInt &V) { return V.getBitWidth() > 1; }
};
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 6139b5be85be..749374a3aa48 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -751,7 +751,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
const DataLayout &DL) {
APInt Offset(DL.getIndexTypeSizeInBits(C->getType()), 0);
- return ConstantFoldLoadFromConstPtr(C, Ty, Offset, DL);
+ return ConstantFoldLoadFromConstPtr(C, Ty, std::move(Offset), DL);
}
Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty,
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 7a37ae86c7f3..9ff3faff7990 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6115,7 +6115,8 @@ static Value *simplifyRelativeLoad(Constant *Ptr, Constant *Offset,
if (OffsetInt.srem(4) != 0)
return nullptr;
- Constant *Loaded = ConstantFoldLoadFromConstPtr(Ptr, Int32Ty, OffsetInt, DL);
+ Constant *Loaded =
+ ConstantFoldLoadFromConstPtr(Ptr, Int32Ty, std::move(OffsetInt), DL);
if (!Loaded)
return nullptr;
@@ -6983,7 +6984,8 @@ Value *llvm::simplifyLoadInst(LoadInst *LI, Value *PtrOp,
if (PtrOp == GV) {
// Index size may have changed due to address space casts.
Offset = Offset.sextOrTrunc(Q.DL.getIndexTypeSizeInBits(PtrOp->getType()));
- return ConstantFoldLoadFromConstPtr(GV, LI->getType(), Offset, Q.DL);
+ return ConstantFoldLoadFromConstPtr(GV, LI->getType(), std::move(Offset),
+ Q.DL);
}
return nullptr;
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 58e0f21244f7..7c67e191348e 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -441,7 +441,7 @@ template <> struct MDNodeKeyImpl {
bool IsUnsigned;
MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name)
- : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
+ : Value(std::move(Value)), Name(Name), IsUnsigned(IsUnsigned) {}
MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
: Value(APInt(64, Value, !IsUnsigned)), Name(Name),
IsUnsigned(IsUnsigned) {}
diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
index 1e0906717549..2bd13556c696 100644
--- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp
+++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
@@ -74,7 +74,7 @@ namespace {
struct BCEAtom {
BCEAtom() = default;
BCEAtom(GetElementPtrInst *GEP, LoadInst *LoadI, int BaseId, APInt Offset)
- : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(Offset) {}
+ : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(std::move(Offset)) {}
BCEAtom(const BCEAtom &) = delete;
BCEAtom &operator=(const BCEAtom &) = delete;
--
GitLab
From ef57977f2aa32661a09fa6538f47ddee0a004d11 Mon Sep 17 00:00:00 2001
From: paperchalice
Date: Sat, 23 Mar 2024 15:02:27 +0800
Subject: [PATCH 012/879] [NewPM][Hexagon] Add HexagonPassRegistry.def (#86244)
Prepare for dag-isel, also migrate some test case
---
.../Target/Hexagon/HexagonPassRegistry.def | 21 +++++++++++++++++++
.../Target/Hexagon/HexagonTargetMachine.cpp | 3 +++
.../hexagon_vector_loop_carried_reuse.ll | 2 +-
...n_vector_loop_carried_reuse_commutative.ll | 2 +-
...agon_vector_loop_carried_reuse_constant.ll | 2 +-
...xagon_vector_loop_carried_reuse_invalid.ll | 2 +-
.../CodeGen/Hexagon/hvx-loopidiom-memcpy.ll | 1 +
.../Hexagon/loop-idiom/hexagon-memmove1.ll | 2 ++
.../Hexagon/loop-idiom/hexagon-memmove2.ll | 2 ++
llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll | 2 +-
.../Hexagon/loop-idiom/memmove-rt-check.ll | 1 +
.../Hexagon/loop-idiom/nullptr-crash.ll | 1 +
.../Hexagon/loop-idiom/pmpy-infinite-loop.ll | 1 +
.../Hexagon/loop-idiom/pmpy-long-loop.ll | 1 +
.../Hexagon/loop-idiom/pmpy-shiftconv-fail.ll | 1 +
llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll | 2 ++
16 files changed, 41 insertions(+), 5 deletions(-)
create mode 100644 llvm/lib/Target/Hexagon/HexagonPassRegistry.def
diff --git a/llvm/lib/Target/Hexagon/HexagonPassRegistry.def b/llvm/lib/Target/Hexagon/HexagonPassRegistry.def
new file mode 100644
index 000000000000..4f58ae6193e0
--- /dev/null
+++ b/llvm/lib/Target/Hexagon/HexagonPassRegistry.def
@@ -0,0 +1,21 @@
+//===- HexagonPassRegistry.def - Registry of Hexagon 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is used as the registry of passes that are part of the
+// Hexagon backend.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef LOOP_PASS
+#define LOOP_PASS(NAME, CREATE_PASS)
+#endif
+LOOP_PASS("hexagon-loop-idiom", HexagonLoopIdiomRecognitionPass())
+LOOP_PASS("hexagon-vlcr", HexagonVectorLoopCarriedReusePass())
+#undef LOOP_PASS
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
index 3c346c334d6d..e64d7e52a9aa 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
@@ -299,6 +299,9 @@ HexagonTargetMachine::getSubtargetImpl(const Function &F) const {
void HexagonTargetMachine::registerPassBuilderCallbacks(
PassBuilder &PB, bool PopulateClassToPassNames) {
+#define GET_PASS_REGISTRY "HexagonPassRegistry.def"
+#include "llvm/Passes/TargetPassRegistry.inc"
+
PB.registerLateLoopOptimizationsEPCallback(
[=](LoopPassManager &LPM, OptimizationLevel Level) {
LPM.addPass(HexagonLoopIdiomRecognitionPass());
diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll
index 0771fda02cfb..7ccee1689185 100644
--- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll
+++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -hexagon-vlcr | opt -passes=adce -S | FileCheck %s
+; RUN: opt -mtriple=hexagon-- -passes='loop(hexagon-vlcr),adce' -S %s | FileCheck %s
; CHECK: %.hexagon.vlcr = tail call <32 x i32> @llvm.hexagon.V6.vmaxub.128B
; ModuleID = 'hexagon_vector_loop_carried_reuse.c'
diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll
index 25afb9f1a137..532f7fd06793 100644
--- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll
+++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -march=hexagon -hexagon-vlcr | opt -passes=adce -S | FileCheck %s
+; RUN: opt -mtriple hexagon-- -passes='loop(hexagon-vlcr),adce' -S %s | FileCheck %s
; CHECK: %v32.hexagon.vlcr = tail call <32 x i32> @llvm.hexagon.V6.vmaxub.128B
diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll
index 53973423732c..ecfcf53d9133 100644
--- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll
+++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -hexagon-vlcr | opt -passes=adce -S | FileCheck %s
+; RUN: opt -mtriple=hexagon-- -passes='loop(hexagon-vlcr),adce' -S %s | FileCheck %s
; CHECK-NOT: %.hexagon.vlcr
; ModuleID = 'hexagon_vector_loop_carried_reuse.c'
diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll
index b440dba66f67..9872faeb3da0 100644
--- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll
+++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll
@@ -1,4 +1,4 @@
-; RUN: opt -hexagon-vlcr < %s -S | FileCheck %s
+; RUN: opt -mtriple=hexagon-- -passes=hexagon-vlcr -S %s | FileCheck %s
; Test that reuse doesn't occur due to two shufflevectors with different masks.
diff --git a/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll b/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll
index ab7bf1b4b0e8..c53e57800edd 100644
--- a/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll
+++ b/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll
@@ -1,4 +1,5 @@
; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s
+; RUN: opt -mtriple=hexagon-- -p hexagon-loop-idiom -disable-memcpy-idiom -S < %s | FileCheck %s
; Make sure we don't convert load/store loops into memcpy if the access type
; is a vector. Using vector instructions is generally better in such cases.
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll
index c7110263c658..5ace9e6ee486 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll
@@ -1,6 +1,8 @@
; Check for recognizing the "memmove" idiom.
; RUN: opt -hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \
; RUN: | FileCheck %s
+; RUN: opt -p hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \
+; RUN: | FileCheck %s
; CHECK: call void @llvm.memmove
; Function Attrs: norecurse nounwind
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll
index 234e4f56b5d8..ed56a332f657 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll
@@ -1,5 +1,7 @@
; RUN: opt -hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \
; RUN: | FileCheck %s
+; RUN: opt -p hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \
+; RUN: | FileCheck %s
define void @PR14241(ptr %s, i64 %size) #0 {
; Ensure that we don't form a memcpy for strided loops. Briefly, when we taught
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll
index 140c676175ea..e5bcc2b9aebf 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -hexagon-loop-idiom < %s | opt -S -passes='loop(loop-deletion),gvn'
+; RUN: opt -mtriple hexagon-- -S -passes='loop(hexagon-loop-idiom,loop-deletion),gvn'
; REQUIRES: asserts
; This tests that the HexagonLoopIdiom pass does not mark LCSSA information
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll
index 7a7d1d9b1a86..78f0c9e36b55 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll
@@ -1,4 +1,5 @@
; RUN: opt -hexagon-loop-idiom -S < %s | FileCheck %s
+; RUN: opt -p hexagon-loop-idiom -S < %s | FileCheck %s
; Make sure that we generate correct runtime checks.
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll
index 37e1bb6eb7df..ce02b62911c0 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll
@@ -1,4 +1,5 @@
; RUN: opt -hexagon-loop-idiom -mtriple hexagon-unknown-elf < %s
+; RUN: opt -p hexagon-loop-idiom -mtriple hexagon-unknown-elf < %s
; REQUIRES: asserts
target triple = "hexagon"
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll
index 1934ced7e7ae..74c02d63d54d 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll
@@ -1,4 +1,5 @@
; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s
+; RUN: opt -march=hexagon -p hexagon-loop-idiom -S < %s | FileCheck %s
; CHECK-LABEL: define void @fred
; Check that this test does not crash.
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll
index b25010f2a90f..94b0c96c3d51 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll
@@ -1,4 +1,5 @@
; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s
+; RUN: opt -march=hexagon -p hexagon-loop-idiom -S < %s | FileCheck %s
;
; The number of nested selects caused the simplification loop to take
; more than the maximum number of iterations. This caused the compiler
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll
index e4b2b5a298ed..a00b1d5876ba 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll
@@ -1,4 +1,5 @@
; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s
+; RUN: opt -march=hexagon -p hexagon-loop-idiom -S < %s | FileCheck %s
; REQUIRES: asserts
;
; Check for sane output, this used to crash.
diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll
index 781618e58901..2461e1cfde8d 100644
--- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll
+++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll
@@ -1,5 +1,7 @@
; RUN: opt -hexagon-loop-idiom < %s -mtriple=hexagon-unknown-unknown -S \
; RUN: | FileCheck %s
+; RUN: opt -p hexagon-loop-idiom < %s -mtriple=hexagon-unknown-unknown -S \
+; RUN: | FileCheck %s
target triple = "hexagon"
--
GitLab
From 691b97c884a15a7eac641ddf67c9f2f30fb4e747 Mon Sep 17 00:00:00 2001
From: Fangrui Song
Date: Sat, 23 Mar 2024 01:02:08 -0700
Subject: [PATCH 013/879] [ELF] Remove zero-value DT_JMPREL when IPLT is
present while PLT isn't
The zero-value DT_JMPREL is benign but not needed.
This is also code simplification available after https://reviews.llvm.org/D65651
---
lld/ELF/SyntheticSections.cpp | 16 ++-------------
.../ELF/aarch64-gnu-ifunc-nonpreemptable.s | 12 +++++------
lld/test/ELF/gnu-ifunc-dyntags.s | 8 +++-----
lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s | 8 ++++----
lld/test/ELF/riscv-ifunc-nonpreemptible.s | 20 +++++++++----------
5 files changed, 25 insertions(+), 39 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 248ff6b4a865..10eda17f0cb3 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1285,13 +1285,7 @@ static uint64_t addRelaSz(const RelocationBaseSection &relaDyn) {
// output section. When this occurs we cannot just use the OutputSection
// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to
// overlap with the [DT_RELA, DT_RELA + DT_RELASZ).
-static uint64_t addPltRelSz() {
- size_t size = in.relaPlt->getSize();
- if (in.relaIplt->getParent() == in.relaPlt->getParent() &&
- in.relaIplt->name == in.relaPlt->name)
- size += in.relaIplt->getSize();
- return size;
-}
+static uint64_t addPltRelSz() { return in.relaPlt->getSize(); }
// Add remaining entries to complete .dynamic contents.
template
@@ -1407,13 +1401,7 @@ DynamicSection::computeContents() {
addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
sizeof(Elf_Relr));
}
- // .rel[a].plt section usually consists of two parts, containing plt and
- // iplt relocations. It is possible to have only iplt relocations in the
- // output. In that case relaPlt is empty and have zero offset, the same offset
- // as relaIplt has. And we still want to emit proper dynamic tags for that
- // case, so here we always use relaPlt as marker for the beginning of
- // .rel[a].plt section.
- if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded())) {
+ if (isMain && in.relaPlt->isNeeded()) {
addInSec(DT_JMPREL, *in.relaPlt);
entries.emplace_back(DT_PLTRELSZ, addPltRelSz());
switch (config->emachine) {
diff --git a/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s b/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s
index 4f33dde9d1a9..54a27a8cc0d9 100644
--- a/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s
+++ b/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s
@@ -65,14 +65,14 @@ main:
# PIE-EMPTY:
# PIE-NEXT: :
# PIE-NEXT: 10270: adrp x16, 0x30000
-# PIE-NEXT: 10274: ldr x17, [x16, #896]
-# PIE-NEXT: 10278: add x16, x16, #896
-# PIE-NEXT: 1027c: br x17
+# PIE-NEXT: ldr x17, [x16, #832]
+# PIE-NEXT: add x16, x16, #832
+# PIE-NEXT: br x17
# PIE-RELOC: .rela.dyn {
-# PIE-RELOC-NEXT: 0x30380 R_AARCH64_IRELATIVE - 0x10260
+# PIE-RELOC-NEXT: 0x30340 R_AARCH64_IRELATIVE - 0x10260
# PIE-RELOC-NEXT: }
# PIE-RELOC: Hex dump of section '.got.plt':
-# NO-APPLY: 0x00030380 00000000 00000000
-# APPLY: 0x00030380 60020100 00000000
+# NO-APPLY: 0x00030340 00000000 00000000
+# APPLY: 0x00030340 60020100 00000000
# PIE-RELOC-EMPTY:
diff --git a/lld/test/ELF/gnu-ifunc-dyntags.s b/lld/test/ELF/gnu-ifunc-dyntags.s
index fd80dc24f2f8..57a17245a3e8 100644
--- a/lld/test/ELF/gnu-ifunc-dyntags.s
+++ b/lld/test/ELF/gnu-ifunc-dyntags.s
@@ -9,15 +9,13 @@
# CHECK: Name Size VMA
# CHECK: .rela.dyn 00000030 0000000000000248
-# CHECK: .got.plt 00000010 00000000000033b0
+# CHECK: .got.plt 00000010 0000000000003370
# TAGS: Tag Type Name/Value
# TAGS: 0x0000000000000007 RELA 0x248
# TAGS: 0x0000000000000008 RELASZ 48 (bytes)
-# TAGS: 0x0000000000000017 JMPREL 0x0
-# TAGS: 0x0000000000000002 PLTRELSZ 0 (bytes)
-# TAGS: 0x0000000000000003 PLTGOT 0x33B0
-# TAGS: 0x0000000000000014 PLTREL RELA
+# TAGS-NOT: JMPREL
+# TAGS-NOT: PLTREL
# TAGS: Relocations [
# TAGS-NEXT: Section {{.*}} .rela.dyn {
diff --git a/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s b/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s
index a93f3cecb0c6..c9a0381b610a 100644
--- a/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s
+++ b/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s
@@ -10,16 +10,16 @@
# RUN: llvm-readelf -x .got2 %t | FileCheck --check-prefix=HEX2 %s
# RELOC: .rela.dyn {
-# RELOC-NEXT: 0x3024C R_PPC_RELATIVE - 0x101A0
-# RELOC-NEXT: 0x30250 R_PPC_IRELATIVE - 0x10188
+# RELOC-NEXT: 0x3022C R_PPC_RELATIVE - 0x101A0
+# RELOC-NEXT: 0x30230 R_PPC_IRELATIVE - 0x10188
# RELOC-NEXT: }
# SYM: 000101a0 0 FUNC GLOBAL DEFAULT {{.*}} func
# HEX: Hex dump of section '.got2':
-# HEX-NEXT: 0x0003024c 00000000 ....
+# HEX-NEXT: 0x0003022c 00000000 ....
# HEX2: Hex dump of section '.got2':
-# HEX2-NEXT: 0x0003024c 000101a0 ....
+# HEX2-NEXT: 0x0003022c 000101a0 ....
.section .got2,"aw"
.long func
diff --git a/lld/test/ELF/riscv-ifunc-nonpreemptible.s b/lld/test/ELF/riscv-ifunc-nonpreemptible.s
index 21c607545110..eda5548eef8b 100644
--- a/lld/test/ELF/riscv-ifunc-nonpreemptible.s
+++ b/lld/test/ELF/riscv-ifunc-nonpreemptible.s
@@ -16,11 +16,11 @@
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefix=DIS64 %s
# RELOC32: .rela.dyn {
-# RELOC32-NEXT: 0x3220 R_RISCV_IRELATIVE - 0x117C
+# RELOC32-NEXT: 0x3200 R_RISCV_IRELATIVE - 0x117C
# RELOC32-NEXT: }
# RELOC32-LABEL: Hex dump of section '.got.plt':
-# NO-APPLY-RELOC32: 0x00003220 00000000
-# APPLY-RELOC32: 0x00003220 7c110000
+# NO-APPLY-RELOC32: 0x00003200 00000000
+# APPLY-RELOC32: 0x00003200 7c110000
# RELOC32-EMPTY:
# SYM32: 0001190 0 FUNC GLOBAL DEFAULT {{.*}} func
@@ -30,18 +30,18 @@
# DIS32-NEXT: addi a0, a0, 0x10
# DIS32: Disassembly of section .iplt:
# DIS32: :
-## 32-bit: &.got.plt[func]-. = 0x3220-0x1190 = 4096*2+144
+## 32-bit: &.got.plt[func]-. = 0x3200-0x1190 = 4096*2+0x70
# DIS32-NEXT: 1190: auipc t3, 0x2
-# DIS32-NEXT: lw t3, 0x90(t3)
+# DIS32-NEXT: lw t3, 0x70(t3)
# DIS32-NEXT: jalr t1, t3
# DIS32-NEXT: nop
# RELOC64: .rela.dyn {
-# RELOC64-NEXT: 0x3380 R_RISCV_IRELATIVE - 0x1260
+# RELOC64-NEXT: 0x3340 R_RISCV_IRELATIVE - 0x1260
# RELOC64-NEXT: }
# RELOC64-LABEL: Hex dump of section '.got.plt':
-# NO-APPLY-RELOC64: 0x00003380 00000000 00000000
-# APPLY-RELOC64: 0x00003380 60120000 00000000
+# NO-APPLY-RELOC64: 0x00003340 00000000 00000000
+# APPLY-RELOC64: 0x00003340 60120000 00000000
# RELOC64-EMPTY:
# SYM64: 000000000001270 0 FUNC GLOBAL DEFAULT {{.*}} func
@@ -51,9 +51,9 @@
# DIS64-NEXT: addi a0, a0, 0xc
# DIS64: Disassembly of section .iplt:
# DIS64: :
-## 64-bit: &.got.plt[func]-. = 0x3380-0x1270 = 4096*2+272
+## 64-bit: &.got.plt[func]-. = 0x3340-0x1270 = 4096*2+0xd0
# DIS64-NEXT: 1270: auipc t3, 0x2
-# DIS64-NEXT: ld t3, 0x110(t3)
+# DIS64-NEXT: ld t3, 0xd0(t3)
# DIS64-NEXT: jalr t1, t3
# DIS64-NEXT: nop
--
GitLab
From 579dc7f8441a8044b92bdfa6f0db2f91301c0eed Mon Sep 17 00:00:00 2001
From: Owen Pan
Date: Sat, 23 Mar 2024 02:03:45 -0700
Subject: [PATCH 014/879] [clang-forma] Support `PointerAlignment` for pointers
to members (#86253)
Fixes #85761.
---
clang/lib/Format/TokenAnnotator.cpp | 37 +++++++++++-------
clang/unittests/Format/FormatTest.cpp | 38 ++++++++++++-------
clang/unittests/Format/QualifierFixerTest.cpp | 36 +++++++++---------
3 files changed, 66 insertions(+), 45 deletions(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index a5cafcbacaa5..7757c8ff7639 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4357,9 +4357,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))
return false;
+ const auto *BeforeLeft = Left.Previous;
+
// operator co_await(x)
- if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous &&
- Left.Previous->is(tok::kw_operator)) {
+ if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft &&
+ BeforeLeft->is(tok::kw_operator)) {
return false;
}
// co_await (x), co_yield (x), co_return (x)
@@ -4394,8 +4396,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
}
if (Left.is(tok::colon))
return Left.isNot(TT_ObjCMethodExpr);
- if (Left.is(tok::coloncolon))
- return false;
+ if (Left.is(tok::coloncolon)) {
+ return Right.is(tok::star) && Right.is(TT_PointerOrReference) &&
+ Style.PointerAlignment != FormatStyle::PAS_Left;
+ }
if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {
if (Style.Language == FormatStyle::LK_TextProto ||
(Style.Language == FormatStyle::LK_Proto &&
@@ -4410,8 +4414,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
}
if (Right.is(tok::ellipsis)) {
- return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
- Left.Previous->is(tok::kw_case));
+ return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft &&
+ BeforeLeft->is(tok::kw_case));
}
if (Left.is(tok::l_square) && Right.is(tok::amp))
return Style.SpacesInSquareBrackets;
@@ -4479,8 +4483,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.is(tok::l_brace) && Right.is(BK_Block))
return true;
// for (auto a = 0, b = 0; const auto& c : {1, 2, 3})
- if (Left.Previous && Left.Previous->isTypeOrIdentifier(IsCpp) &&
- Right.Next && Right.Next->is(TT_RangeBasedForLoopColon)) {
+ if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(IsCpp) && Right.Next &&
+ Right.Next->is(TT_RangeBasedForLoopColon)) {
return getTokenPointerOrReferenceAlignment(Left) !=
FormatStyle::PAS_Right;
}
@@ -4502,12 +4506,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
startsWithInitStatement(Line)))) {
return false;
}
- return Left.Previous && !Left.Previous->isOneOf(
- tok::l_paren, tok::coloncolon, tok::l_square);
+ if (!BeforeLeft)
+ return false;
+ if (BeforeLeft->is(tok::coloncolon)) {
+ return Left.is(tok::star) &&
+ Style.PointerAlignment != FormatStyle::PAS_Right;
+ }
+ return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square);
}
// Ensure right pointer alignment with ellipsis e.g. int *...P
- if (Left.is(tok::ellipsis) && Left.Previous &&
- Left.Previous->isPointerOrReference()) {
+ if (Left.is(tok::ellipsis) && BeforeLeft &&
+ BeforeLeft->isPointerOrReference()) {
return Style.PointerAlignment != FormatStyle::PAS_Right;
}
@@ -4669,13 +4678,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
spaceRequiredBeforeParens(Right);
}
- if (!Left.Previous || !Left.Previous->isOneOf(tok::period, tok::arrow)) {
+ if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) {
if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) {
return Style.SpaceBeforeParensOptions.AfterControlStatements ||
spaceRequiredBeforeParens(Right);
}
if (Left.isOneOf(tok::kw_new, tok::kw_delete)) {
- return ((!Line.MightBeFunctionDecl || !Left.Previous) &&
+ return ((!Line.MightBeFunctionDecl || !BeforeLeft) &&
Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||
spaceRequiredBeforeParens(Right);
}
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index bea989c8c306..cf8d6ab691d9 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -3621,8 +3621,8 @@ TEST_F(FormatTest, FormatsClasses) {
" : public aaaaaaaaaaaaaaaaaaa {};");
verifyFormat("template \n"
- "struct Aaaaaaaaaaaaaaaaa\n"
- " : Aaaaaaaaaaaaaaaaa {};");
+ "struct Aaaaaaaaaaaaaaaaa\n"
+ " : Aaaaaaaaaaaaaaaaa {};");
verifyFormat("class ::A::B {};");
}
@@ -11034,10 +11034,10 @@ TEST_F(FormatTest, UnderstandsBinaryOperators) {
}
TEST_F(FormatTest, UnderstandsPointersToMembers) {
- verifyFormat("int A::*x;");
- verifyFormat("int (S::*func)(void *);");
- verifyFormat("void f() { int (S::*func)(void *); }");
- verifyFormat("typedef bool *(Class::*Member)() const;");
+ verifyFormat("int A:: *x;");
+ verifyFormat("int (S:: *func)(void *);");
+ verifyFormat("void f() { int (S:: *func)(void *); }");
+ verifyFormat("typedef bool *(Class:: *Member)() const;");
verifyFormat("void f() {\n"
" (a->*f)();\n"
" a->*x;\n"
@@ -11052,9 +11052,19 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) {
verifyFormat(
"(aaaaaaaaaa->*bbbbbbb)(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));");
+
FormatStyle Style = getLLVMStyle();
+ EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+ verifyFormat("typedef bool *(Class:: *Member)() const;", Style);
+ verifyFormat("void f(int A:: *p) { int A:: *v = &A::B; }", Style);
+
Style.PointerAlignment = FormatStyle::PAS_Left;
- verifyFormat("typedef bool* (Class::*Member)() const;", Style);
+ verifyFormat("typedef bool* (Class::* Member)() const;", Style);
+ verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
+
+ Style.PointerAlignment = FormatStyle::PAS_Middle;
+ verifyFormat("typedef bool * (Class:: * Member)() const;", Style);
+ verifyFormat("void f(int A:: * p) { int A:: * v = &A::B; }", Style);
}
TEST_F(FormatTest, UnderstandsUnaryOperators) {
@@ -12386,7 +12396,7 @@ TEST_F(FormatTest, FormatsFunctionTypes) {
verifyFormat("int (*func)(void *);");
verifyFormat("void f() { int (*func)(void *); }");
verifyFormat("template \n"
- "using MyCallback = void (CallbackClass::*)(SomeObject *Data);");
+ "using Callback = void (CallbackClass:: *)(SomeObject *Data);");
verifyGoogleFormat("A;");
verifyGoogleFormat("void* (*a)(int);");
@@ -19149,13 +19159,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
"int bbbbbbb = 0;",
Alignment);
// http://llvm.org/PR68079
- verifyFormat("using Fn = int (A::*)();\n"
- "using RFn = int (A::*)() &;\n"
- "using RRFn = int (A::*)() &&;",
+ verifyFormat("using Fn = int (A:: *)();\n"
+ "using RFn = int (A:: *)() &;\n"
+ "using RRFn = int (A:: *)() &&;",
Alignment);
- verifyFormat("using Fn = int (A::*)();\n"
- "using RFn = int *(A::*)() &;\n"
- "using RRFn = double (A::*)() &&;",
+ verifyFormat("using Fn = int (A:: *)();\n"
+ "using RFn = int *(A:: *)() &;\n"
+ "using RRFn = double (A:: *)() &&;",
Alignment);
// PAS_Right
diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp
index 43476aea6633..792d8f3c3a98 100644
--- a/clang/unittests/Format/QualifierFixerTest.cpp
+++ b/clang/unittests/Format/QualifierFixerTest.cpp
@@ -305,7 +305,7 @@ TEST_F(QualifierFixerTest, RightQualifier) {
verifyFormat("Foo inline static const;", "Foo inline const static;", Style);
verifyFormat("Foo inline static const;", Style);
- verifyFormat("Foo::Bar const volatile A::*;",
+ verifyFormat("Foo::Bar const volatile A:: *;",
"volatile const Foo::Bar A::*;",
Style);
@@ -523,14 +523,15 @@ TEST_F(QualifierFixerTest, RightQualifier) {
verifyFormat("const INTPTR a;", Style);
// Pointers to members
- verifyFormat("int S::*a;", Style);
- verifyFormat("int const S::*a;", "const int S:: *a;", Style);
- verifyFormat("int const S::*const a;", "const int S::* const a;", Style);
- verifyFormat("int A::*const A::*p1;", Style);
- verifyFormat("float (C::*p)(int);", Style);
- verifyFormat("float (C::*const p)(int);", Style);
- verifyFormat("float (C::*p)(int) const;", Style);
- verifyFormat("float const (C::*p)(int);", "const float (C::*p)(int);", Style);
+ verifyFormat("int S:: *a;", Style);
+ verifyFormat("int const S:: *a;", "const int S:: *a;", Style);
+ verifyFormat("int const S:: *const a;", "const int S::* const a;", Style);
+ verifyFormat("int A:: *const A:: *p1;", Style);
+ verifyFormat("float (C:: *p)(int);", Style);
+ verifyFormat("float (C:: *const p)(int);", Style);
+ verifyFormat("float (C:: *p)(int) const;", Style);
+ verifyFormat("float const (C:: *p)(int);", "const float (C::*p)(int);",
+ Style);
}
TEST_F(QualifierFixerTest, LeftQualifier) {
@@ -830,14 +831,15 @@ TEST_F(QualifierFixerTest, LeftQualifier) {
verifyFormat("INTPTR const a;", Style);
// Pointers to members
- verifyFormat("int S::*a;", Style);
- verifyFormat("const int S::*a;", "int const S:: *a;", Style);
- verifyFormat("const int S::*const a;", "int const S::* const a;", Style);
- verifyFormat("int A::*const A::*p1;", Style);
- verifyFormat("float (C::*p)(int);", Style);
- verifyFormat("float (C::*const p)(int);", Style);
- verifyFormat("float (C::*p)(int) const;", Style);
- verifyFormat("const float (C::*p)(int);", "float const (C::*p)(int);", Style);
+ verifyFormat("int S:: *a;", Style);
+ verifyFormat("const int S:: *a;", "int const S:: *a;", Style);
+ verifyFormat("const int S:: *const a;", "int const S::* const a;", Style);
+ verifyFormat("int A:: *const A:: *p1;", Style);
+ verifyFormat("float (C:: *p)(int);", Style);
+ verifyFormat("float (C:: *const p)(int);", Style);
+ verifyFormat("float (C:: *p)(int) const;", Style);
+ verifyFormat("const float (C:: *p)(int);", "float const (C::*p)(int);",
+ Style);
}
TEST_F(QualifierFixerTest, ConstVolatileQualifiersOrder) {
--
GitLab
From 47423e9827abfdcc6b10ce41618965861b0e69a4 Mon Sep 17 00:00:00 2001
From: Owen Pan
Date: Sat, 23 Mar 2024 02:24:56 -0700
Subject: [PATCH 015/879] [clang-format][NFC] Clean up
IsQualifiedPointerOrReference in TokenAnnotator
---
clang/lib/Format/TokenAnnotator.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 7757c8ff7639..4c83a7a3a323 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2753,10 +2753,9 @@ private:
}
// Heuristically try to determine whether the parentheses contain a type.
- auto IsQualifiedPointerOrReference = [this](FormatToken *T) {
+ auto IsQualifiedPointerOrReference = [](FormatToken *T, bool IsCpp) {
// This is used to handle cases such as x = (foo *const)&y;
assert(!T->isTypeName(IsCpp) && "Should have already been checked");
- (void)IsCpp; // Avoid -Wunused-lambda-capture when assertion is disabled.
// Strip trailing qualifiers such as const or volatile when checking
// whether the parens could be a cast to a pointer/reference type.
while (T) {
@@ -2789,7 +2788,7 @@ private:
!Tok.Previous ||
Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
Tok.Previous->isTypeName(IsCpp) ||
- IsQualifiedPointerOrReference(Tok.Previous);
+ IsQualifiedPointerOrReference(Tok.Previous, IsCpp);
bool ParensCouldEndDecl =
Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
if (ParensAreType && !ParensCouldEndDecl)
--
GitLab
From f317fd266c184bc8f9f4d7e8e03c043d3406333a Mon Sep 17 00:00:00 2001
From: Muhammad Omair Javaid
Date: Sat, 23 Mar 2024 15:30:26 +0500
Subject: [PATCH 016/879] Revert "[mlir][SVE] Add e2e for 1D depthwise WC
convolution (#85225)"
This reverts commit 01b1b0c1f728e2c2639edc654424f50830295989.
Breaks following AArch64 SVE buildbots:
https://lab.llvm.org/buildbot/#/builders/184/builds/11363
https://lab.llvm.org/buildbot/#/builders/176/builds/9331
---
.../Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir | 60 -------------------
1 file changed, 60 deletions(-)
delete mode 100644 mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir
diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir
deleted file mode 100644
index 57d69383c2de..000000000000
--- a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir
+++ /dev/null
@@ -1,60 +0,0 @@
-// DEFINE: %{compile} = mlir-opt %s \
-// DEFINE: -transform-interpreter -test-transform-dialect-erase-schedule \
-// DEFINE: -one-shot-bufferize="bufferize-function-boundaries" -lower-vector-mask -cse -canonicalize -convert-vector-to-scf -arm-sve-legalize-vector-storage \
-// DEFINE: -convert-vector-to-llvm="enable-arm-sve" -test-lower-to-llvm -o %t
-// DEFINE: %{entry_point} = conv
-// DEFINE: %{run} = %mcr_aarch64_cmd %t -e %{entry_point} -entry-point-result=void --march=aarch64 --mattr="+sve"\
-// DEFINE: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils
-
-// RUN: %{compile} | %{run} | FileCheck %s
-
-func.func @conv() {
- // Define input/output tensors
- %input_init = tensor.empty() : tensor<1x8x6xi32>
- %output_init = tensor.empty() : tensor<1x7x6xi32>
-
- %five = arith.constant 5 : i32
- %zero = arith.constant 0 : i32
- %input = linalg.fill ins(%five : i32) outs(%input_init : tensor<1x8x6xi32>) -> tensor<1x8x6xi32>
- %output = linalg.fill ins(%zero : i32) outs(%output_init : tensor<1x7x6xi32>) -> tensor<1x7x6xi32>
-
- // Define the filter tensor
- %filter = arith.constant dense<[
- [ 1, 2, 3, 4, 5, 6],
- [ 11, 12, 13, 14, 15, 16]
- ]> : tensor<2x6xi32>
-
- // static sizes -> dynamic sizes
- %input_dyn = tensor.cast %input_init : tensor<1x8x6xi32> to tensor<1x8x?xi32>
- %output_dyn = tensor.cast %output : tensor<1x7x6xi32> to tensor<1x7x?xi32>
- %filter_dyn = tensor.cast %filter : tensor<2x6xi32> to tensor<2x?xi32>
-
- // Run the convolution
- %res = linalg.depthwise_conv_1d_nwc_wc
- ins(%input_dyn, %filter_dyn : tensor<1x8x?xi32>, tensor<2x?xi32>)
- outs(%output_dyn : tensor<1x7x?xi32>) -> tensor<1x7x?xi32>
-
- // Print the results
- // CHECK: SVE: START OF TEST OUTPUT
- vector.print str "SVE: START OF TEST OUTPUT\n"
-
- // CHECK-NEXT: Unranked Memref base@ = {{.*}} rank = 3 offset = 0 sizes = [1, 7, 6] strides = [42, 6, 1] data =
- // CHECK-COUNT-7: [60, 70, 80, 90, 100, 110]
- %xf = tensor.cast %res : tensor<1x7x?xi32> to tensor<*xi32>
- call @printMemrefI32(%xf) : (tensor<*xi32>) -> ()
-
- // CHECK-NEXT: SVE: END OF TEST OUTPUT
- vector.print str "SVE: END OF TEST OUTPUT\n"
-
- return
-}
-
-module attributes {transform.with_named_sequence} {
- transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
- %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_nwc_wc"]} in %arg0 : (!transform.any_op) -> !transform.any_op
- transform.structured.vectorize %0 vector_sizes [1, 7, [8], 2] : !transform.any_op
- transform.yield
- }
-}
-
-func.func private @printMemrefI32(%ptr : tensor<*xi32>) attributes { llvm.emit_c_interface }
--
GitLab
From d7c672834ec863b458af8ca493157e1e31aaf480 Mon Sep 17 00:00:00 2001
From: XChy
Date: Sat, 23 Mar 2024 19:00:42 +0800
Subject: [PATCH 017/879] [CodeGen][NFC] Update tests in AArch64/and-sink.ll
---
llvm/test/CodeGen/AArch64/and-sink.ll | 60 +++++++++++++++++++++------
1 file changed, 47 insertions(+), 13 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/and-sink.ll b/llvm/test/CodeGen/AArch64/and-sink.ll
index 4d085869de24..f298a55dab72 100644
--- a/llvm/test/CodeGen/AArch64/and-sink.ll
+++ b/llvm/test/CodeGen/AArch64/and-sink.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs < %s | FileCheck %s
; RUN: opt -S -passes='require,function(codegenprepare)' -mtriple=aarch64-linux %s | FileCheck --check-prefix=CHECK-CGP %s
; RUN: opt -S -passes='require,function(codegenprepare)' -cgpp-huge-func=0 -mtriple=aarch64-linux %s | FileCheck --check-prefix=CHECK-CGP %s
@@ -9,9 +10,18 @@
; Test that and is sunk into cmp block to form tbz.
define dso_local i32 @and_sink1(i32 %a, i1 %c) {
; CHECK-LABEL: and_sink1:
-; CHECK: tbz w1, #0
-; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A]
-; CHECK: tbnz {{w[0-9]+}}, #2
+; CHECK: // %bb.0:
+; CHECK-NEXT: tbz w1, #0, .LBB0_3
+; CHECK-NEXT: // %bb.1: // %bb0
+; CHECK-NEXT: adrp x8, A
+; CHECK-NEXT: str wzr, [x8, :lo12:A]
+; CHECK-NEXT: tbnz w0, #2, .LBB0_3
+; CHECK-NEXT: // %bb.2:
+; CHECK-NEXT: mov w0, #1 // =0x1
+; CHECK-NEXT: ret
+; CHECK-NEXT: .LBB0_3: // %bb2
+; CHECK-NEXT: mov w0, wzr
+; CHECK-NEXT: ret
; CHECK-CGP-LABEL: @and_sink1(
; CHECK-CGP-NOT: and i32
@@ -35,12 +45,30 @@ bb2:
; Test that both 'and' and cmp get sunk to form tbz.
define dso_local i32 @and_sink2(i32 %a, i1 %c, i1 %c2) {
; CHECK-LABEL: and_sink2:
-; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A]
-; CHECK: tbz w1, #0
-; CHECK: str wzr, [x{{[0-9]+}}, :lo12:B]
-; CHECK: tbz w2, #0
-; CHECK: str wzr, [x{{[0-9]+}}, :lo12:C]
-; CHECK: tbnz {{w[0-9]+}}, #2
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, wzr
+; CHECK-NEXT: adrp x9, A
+; CHECK-NEXT: str wzr, [x9, :lo12:A]
+; CHECK-NEXT: tbz w1, #0, .LBB1_5
+; CHECK-NEXT: // %bb.1: // %bb0.preheader
+; CHECK-NEXT: adrp x8, B
+; CHECK-NEXT: adrp x9, C
+; CHECK-NEXT: .LBB1_2: // %bb0
+; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: str wzr, [x8, :lo12:B]
+; CHECK-NEXT: tbz w2, #0, .LBB1_6
+; CHECK-NEXT: // %bb.3: // %bb1
+; CHECK-NEXT: // in Loop: Header=BB1_2 Depth=1
+; CHECK-NEXT: str wzr, [x9, :lo12:C]
+; CHECK-NEXT: tbnz w0, #2, .LBB1_2
+; CHECK-NEXT: // %bb.4:
+; CHECK-NEXT: mov w8, #1 // =0x1
+; CHECK-NEXT: .LBB1_5: // %common.ret
+; CHECK-NEXT: mov w0, w8
+; CHECK-NEXT: ret
+; CHECK-NEXT: .LBB1_6:
+; CHECK-NEXT: mov w0, wzr
+; CHECK-NEXT: ret
; CHECK-CGP-LABEL: @and_sink2(
; CHECK-CGP-NOT: and i32
@@ -71,10 +99,16 @@ bb3:
; Test that 'and' is not sunk since cbz is a better alternative.
define dso_local i32 @and_sink3(i32 %a) {
; CHECK-LABEL: and_sink3:
-; CHECK: and [[REG:w[0-9]+]], w0, #0x3
-; CHECK: [[LOOP:.L[A-Z0-9_]+]]:
-; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A]
-; CHECK: cbz [[REG]], [[LOOP]]
+; CHECK: // %bb.0:
+; CHECK-NEXT: adrp x8, A
+; CHECK-NEXT: and w9, w0, #0x3
+; CHECK-NEXT: .LBB2_1: // %bb0
+; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: str wzr, [x8, :lo12:A]
+; CHECK-NEXT: cbz w9, .LBB2_1
+; CHECK-NEXT: // %bb.2: // %bb2
+; CHECK-NEXT: mov w0, wzr
+; CHECK-NEXT: ret
; CHECK-CGP-LABEL: @and_sink3(
; CHECK-CGP-NEXT: and i32
--
GitLab
From d365a45cb3eaa640b09874fb7984a6a69683c773 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov
Date: Sat, 23 Mar 2024 15:12:44 +0300
Subject: [PATCH 018/879] [GlobalISel] Introduce G_TRAP, G_DEBUGTRAP,
G_UBSANTRAP (#84941)
Here we introduce three new GMIR instructions to cover a set of trap
intrinsics. The idea behind it is that generic intrinsics shouldn't be
used with G_INTRINSIC opcode.
These new instructions can match perfectly with existing trap ISD nodes.
It allows X86, AArch64, RISCV and Mips to reuse SelectionDAG patterns for
selection and avoid manual selection. However AMDGPU is an exception. It
selects traps during legalization regardless SelectionDAG or GlobalISel.
Since there are not many places where traps are used, this change
attempts to clean up all the usages of G_INTRINSIC with trap intrinsics. So,
there is no stage when both G_TRAP and
G_INTRINSIC_W_SIDE_EFFECTS(@llvm.trap) are allowed.
---
llvm/docs/GlobalISel/GenericOpcode.rst | 19 +++++
llvm/docs/LangRef.rst | 6 ++
.../llvm/CodeGen/GlobalISel/IRTranslator.h | 4 +
.../CodeGen/GlobalISel/MachineIRBuilder.h | 5 ++
llvm/include/llvm/Support/TargetOpcodes.def | 5 ++
llvm/include/llvm/Target/GenericOpcodes.td | 22 ++++++
.../Target/GlobalISel/SelectionDAGCompat.td | 3 +
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 47 ++++++++----
llvm/lib/CodeGen/MachineVerifier.cpp | 11 +++
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 3 +
.../GISel/AArch64InstructionSelector.cpp | 20 ++---
.../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 23 +++---
llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h | 8 +-
llvm/lib/Target/Mips/MipsLegalizerInfo.cpp | 8 --
.../RISCV/GISel/RISCVInstructionSelector.cpp | 27 -------
.../X86/GISel/X86InstructionSelector.cpp | 19 -----
.../GlobalISel/irtranslator-unreachable.ll | 2 +-
.../AArch64/GlobalISel/legalize-exceptions.ll | 2 +-
.../GlobalISel/legalizer-info-validation.mir | 9 +++
.../AArch64/GlobalISel/select-trap.mir | 2 +-
.../AArch64/GlobalISel/uaddo-8-16-bits.mir | 52 ++++++-------
.../AMDGPU/GlobalISel/legalize-trap.mir | 4 +-
.../trap.mir | 9 ++-
.../GlobalISel/instruction-select/trap.mir | 4 +-
.../X86/GlobalISel/x86-select-trap.mir | 2 +-
llvm/test/CodeGen/X86/isel-traps.ll | 73 +++++++++++++++++++
.../test/MachineVerifier/test_g_ubsantrap.mir | 18 +++++
27 files changed, 276 insertions(+), 131 deletions(-)
rename llvm/test/CodeGen/Mips/GlobalISel/{legalizer => instruction-select}/trap.mir (55%)
create mode 100644 llvm/test/CodeGen/X86/isel-traps.ll
create mode 100644 llvm/test/MachineVerifier/test_g_ubsantrap.mir
diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst
index ac6217d08e6a..cae2c21b80d7 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.rst
+++ b/llvm/docs/GlobalISel/GenericOpcode.rst
@@ -939,6 +939,25 @@ The _CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`.
Unlike SelectionDAG, there is no _VOID variant. Both of these are permitted
to have zero, one, or multiple results.
+G_TRAP, G_DEBUGTRAP, G_UBSANTRAP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Represents :ref:`llvm.trap `, :ref:`llvm.debugtrap `
+and :ref:`llvm.ubsantrap ` that generate a target dependent
+trap instructions.
+
+.. code-block:: none
+
+ G_TRAP
+
+.. code-block:: none
+
+ G_DEBUGTRAP
+
+.. code-block:: none
+
+ G_UBSANTRAP 12
+
Variadic Arguments
------------------
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8bc1cab01bf0..391fd2d960dd 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -26926,6 +26926,8 @@ Arguments:
The argument should be an MDTuple containing any number of MDStrings.
+.. _llvm.trap:
+
'``llvm.trap``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26953,6 +26955,8 @@ This intrinsic is lowered to the target dependent trap instruction. If
the target does not have a trap instruction, this intrinsic will be
lowered to a call of the ``abort()`` function.
+.. _llvm.debugtrap:
+
'``llvm.debugtrap``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26980,6 +26984,8 @@ This intrinsic is lowered to code which is intended to cause an
execution trap with the intention of requesting the attention of a
debugger.
+.. _llvm.ubsantrap:
+
'``llvm.ubsantrap``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 6ae7c1440907..5f28908e998a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -243,6 +243,10 @@ private:
bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
unsigned Opcode);
+ /// Translate an LLVM trap intrinsic (trap, debugtrap, ubsantrap).
+ bool translateTrap(const CallInst &U, MachineIRBuilder &MIRBuilder,
+ unsigned Opcode);
+
// Translate @llvm.experimental.vector.interleave2 and
// @llvm.experimental.vector.deinterleave2 intrinsics for fixed-width vector
// types into vector shuffles.
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index aaa81342845b..3ba036ae713f 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -2113,6 +2113,11 @@ public:
DstMMO, SrcMMO);
}
+ /// Build and insert G_TRAP or G_DEBUGTRAP
+ MachineInstrBuilder buildTrap(bool Debug = false) {
+ return buildInstr(Debug ? TargetOpcode::G_DEBUGTRAP : TargetOpcode::G_TRAP);
+ }
+
/// Build and insert \p Dst = G_SBFX \p Src, \p LSB, \p Width.
MachineInstrBuilder buildSbfx(const DstOp &Dst, const SrcOp &Src,
const SrcOp &LSB, const SrcOp &Width) {
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 899eaad5842a..5765926d6d93 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -837,6 +837,11 @@ HANDLE_TARGET_OPCODE(G_MEMMOVE)
HANDLE_TARGET_OPCODE(G_MEMSET)
HANDLE_TARGET_OPCODE(G_BZERO)
+/// llvm.trap, llvm.debugtrap and llvm.ubsantrap intrinsics
+HANDLE_TARGET_OPCODE(G_TRAP)
+HANDLE_TARGET_OPCODE(G_DEBUGTRAP)
+HANDLE_TARGET_OPCODE(G_UBSANTRAP)
+
/// Vector reductions
HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FADD)
HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FMUL)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 67d405ba96fa..d0f471eb29b6 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1575,6 +1575,28 @@ def G_BZERO : GenericInstruction {
let mayStore = true;
}
+//------------------------------------------------------------------------------
+// Trap intrinsics
+//------------------------------------------------------------------------------
+def G_TRAP : GenericInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let hasSideEffects = true;
+ let mayStore = true;
+}
+
+def G_DEBUGTRAP : GenericInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let hasSideEffects = true;
+}
+
+def G_UBSANTRAP : GenericInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins i8imm:$kind);
+ let hasSideEffects = true;
+}
+
//------------------------------------------------------------------------------
// Bitfield extraction.
//------------------------------------------------------------------------------
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index b1f3c500a1b6..4bb9929e2cf8 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -250,6 +250,9 @@ def : GINodeEquiv;
def : GINodeEquiv;
def : GINodeEquiv;
def : GINodeEquiv;
+def : GINodeEquiv;
+def : GINodeEquiv;
+def : GINodeEquiv;
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
// Should be used on defs that subclass GIComplexOperandMatcher<>.
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 757af3b1c4fe..ef95ceec18a1 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1771,6 +1771,32 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
return true;
}
+bool IRTranslator::translateTrap(const CallInst &CI,
+ MachineIRBuilder &MIRBuilder,
+ unsigned Opcode) {
+ StringRef TrapFuncName =
+ CI.getAttributes().getFnAttr("trap-func-name").getValueAsString();
+ if (TrapFuncName.empty()) {
+ if (Opcode == TargetOpcode::G_UBSANTRAP) {
+ uint64_t Code = cast(CI.getOperand(0))->getZExtValue();
+ MIRBuilder.buildInstr(Opcode, {}, ArrayRef{Code});
+ } else {
+ MIRBuilder.buildInstr(Opcode);
+ }
+ return true;
+ }
+
+ CallLowering::CallLoweringInfo Info;
+ if (Opcode == TargetOpcode::G_UBSANTRAP)
+ Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)),
+ CI.getArgOperand(0)->getType(), 0});
+
+ Info.Callee = MachineOperand::CreateES(TrapFuncName.data());
+ Info.CB = &CI;
+ Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0};
+ return CLI->lowerCall(MIRBuilder, Info);
+}
+
bool IRTranslator::translateVectorInterleave2Intrinsic(
const CallInst &CI, MachineIRBuilder &MIRBuilder) {
assert(CI.getIntrinsicID() == Intrinsic::experimental_vector_interleave2 &&
@@ -2459,22 +2485,11 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
return true;
}
case Intrinsic::trap:
+ return translateTrap(CI, MIRBuilder, TargetOpcode::G_TRAP);
case Intrinsic::debugtrap:
- case Intrinsic::ubsantrap: {
- StringRef TrapFuncName =
- CI.getAttributes().getFnAttr("trap-func-name").getValueAsString();
- if (TrapFuncName.empty())
- break; // Use the default handling.
- CallLowering::CallLoweringInfo Info;
- if (ID == Intrinsic::ubsantrap) {
- Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)),
- CI.getArgOperand(0)->getType(), 0});
- }
- Info.Callee = MachineOperand::CreateES(TrapFuncName.data());
- Info.CB = &CI;
- Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0};
- return CLI->lowerCall(MIRBuilder, Info);
- }
+ return translateTrap(CI, MIRBuilder, TargetOpcode::G_DEBUGTRAP);
+ case Intrinsic::ubsantrap:
+ return translateTrap(CI, MIRBuilder, TargetOpcode::G_UBSANTRAP);
case Intrinsic::amdgcn_cs_chain:
return translateCallBase(CI, MIRBuilder);
case Intrinsic::fptrunc_round: {
@@ -3047,7 +3062,7 @@ bool IRTranslator::translateUnreachable(const User &U, MachineIRBuilder &MIRBuil
}
}
- MIRBuilder.buildIntrinsic(Intrinsic::trap, ArrayRef());
+ MIRBuilder.buildTrap();
return true;
}
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 005efe48ac0c..9a1498d4070e 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1867,6 +1867,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
break;
}
+ case TargetOpcode::G_UBSANTRAP: {
+ const MachineOperand &KindOp = MI->getOperand(0);
+ if (!MI->getOperand(0).isImm()) {
+ report("Crash kind must be an immediate", &KindOp, 0);
+ break;
+ }
+ int64_t Kind = MI->getOperand(0).getImm();
+ if (!isInt<8>(Kind))
+ report("Crash kind must be 8 bit wide", &KindOp, 0);
+ break;
+ }
case TargetOpcode::G_VECREDUCE_SEQ_FADD:
case TargetOpcode::G_VECREDUCE_SEQ_FMUL: {
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index b4b975cce007..b1f514f75207 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -8436,6 +8436,9 @@ def ubsan_trap_xform : SDNodeXFormgetTargetConstant(N->getZExtValue() | ('U' << 8), SDLoc(N), MVT::i32);
}]>;
+def gi_ubsan_trap_xform : GICustomOperandRenderer<"renderUbsanTrap">,
+ GISDNodeXFormEquiv;
+
def ubsan_trap_imm : TImmLeaf(Imm);
}], ubsan_trap_xform>;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 677dd0b502b9..a8f2c45279e6 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -479,6 +479,8 @@ private:
int OpIdx = -1) const;
void renderLogicalImm64(MachineInstrBuilder &MIB, const MachineInstr &I,
int OpIdx = -1) const;
+ void renderUbsanTrap(MachineInstrBuilder &MIB, const MachineInstr &MI,
+ int OpIdx) const;
void renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI,
int OpIdx = -1) const;
void renderFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI,
@@ -6159,16 +6161,6 @@ bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
constrainSelectedInstRegOperands(*NewI, TII, TRI, RBI);
break;
}
- case Intrinsic::trap:
- MIB.buildInstr(AArch64::BRK, {}, {}).addImm(1);
- break;
- case Intrinsic::debugtrap:
- MIB.buildInstr(AArch64::BRK, {}, {}).addImm(0xF000);
- break;
- case Intrinsic::ubsantrap:
- MIB.buildInstr(AArch64::BRK, {}, {})
- .addImm(I.getOperand(1).getImm() | ('U' << 8));
- break;
case Intrinsic::aarch64_neon_ld1x2: {
LLT Ty = MRI.getType(I.getOperand(0).getReg());
unsigned Opc = 0;
@@ -7663,6 +7655,14 @@ void AArch64InstructionSelector::renderLogicalImm64(
MIB.addImm(Enc);
}
+void AArch64InstructionSelector::renderUbsanTrap(MachineInstrBuilder &MIB,
+ const MachineInstr &MI,
+ int OpIdx) const {
+ assert(MI.getOpcode() == TargetOpcode::G_UBSANTRAP && OpIdx == 0 &&
+ "Expected G_UBSANTRAP");
+ MIB.addImm(MI.getOperand(0).getImm() | ('U' << 8));
+}
+
void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB,
const MachineInstr &MI,
int OpIdx) const {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 90872516dd6d..e55d1de01b4f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -2030,6 +2030,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
getActionDefinitionsBuilder({G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET})
.lower();
+ getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
+
getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
@@ -2134,6 +2136,10 @@ bool AMDGPULegalizerInfo::legalizeCustom(
return legalizeGetFPEnv(MI, MRI, B);
case TargetOpcode::G_SET_FPENV:
return legalizeSetFPEnv(MI, MRI, B);
+ case TargetOpcode::G_TRAP:
+ return legalizeTrap(MI, MRI, B);
+ case TargetOpcode::G_DEBUGTRAP:
+ return legalizeDebugTrap(MI, MRI, B);
default:
return false;
}
@@ -2925,7 +2931,7 @@ bool AMDGPULegalizerInfo::legalizeGlobalValue(
// functions that use local objects. However, if these dead functions are
// not eliminated, we don't want a compile time error. Just emit a warning
// and a trap, since there should be no callable path here.
- B.buildIntrinsic(Intrinsic::trap, ArrayRef());
+ B.buildTrap();
B.buildUndef(DstReg);
MI.eraseFromParent();
return true;
@@ -6618,9 +6624,9 @@ bool AMDGPULegalizerInfo::legalizeSBufferLoad(LegalizerHelper &Helper,
}
// TODO: Move to selection
-bool AMDGPULegalizerInfo::legalizeTrapIntrinsic(MachineInstr &MI,
- MachineRegisterInfo &MRI,
- MachineIRBuilder &B) const {
+bool AMDGPULegalizerInfo::legalizeTrap(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ MachineIRBuilder &B) const {
if (!ST.isTrapHandlerEnabled() ||
ST.getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
return legalizeTrapEndpgm(MI, MRI, B);
@@ -6726,8 +6732,9 @@ bool AMDGPULegalizerInfo::legalizeTrapHsa(
return true;
}
-bool AMDGPULegalizerInfo::legalizeDebugTrapIntrinsic(
- MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const {
+bool AMDGPULegalizerInfo::legalizeDebugTrap(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ MachineIRBuilder &B) const {
// Is non-HSA path or trap-handler disabled? Then, report a warning
// accordingly
if (!ST.isTrapHandlerEnabled() ||
@@ -7270,10 +7277,6 @@ bool AMDGPULegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
case Intrinsic::amdgcn_struct_buffer_atomic_fadd_v2bf16:
case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd_v2bf16:
return legalizeBufferAtomic(MI, B, IntrID);
- case Intrinsic::trap:
- return legalizeTrapIntrinsic(MI, MRI, B);
- case Intrinsic::debugtrap:
- return legalizeDebugTrapIntrinsic(MI, MRI, B);
case Intrinsic::amdgcn_rsq_clamp:
return legalizeRsqClampIntrinsic(MI, MRI, B);
case Intrinsic::amdgcn_ds_fadd:
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h
index 9661646fffc9..e5ba84a74a0f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h
@@ -226,16 +226,16 @@ public:
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const;
- bool legalizeTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
- MachineIRBuilder &B) const;
+ bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI,
+ MachineIRBuilder &B) const;
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const;
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const;
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const;
- bool legalizeDebugTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
- MachineIRBuilder &B) const;
+ bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI,
+ MachineIRBuilder &B) const;
bool legalizeIntrinsic(LegalizerHelper &Helper,
MachineInstr &MI) const override;
diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
index 3307e840a2af..8468dd6a2211 100644
--- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
@@ -508,16 +508,8 @@ bool MipsLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
MachineInstr &MI) const {
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
const MipsSubtarget &ST = MI.getMF()->getSubtarget();
- const MipsInstrInfo &TII = *ST.getInstrInfo();
- const MipsRegisterInfo &TRI = *ST.getRegisterInfo();
- const RegisterBankInfo &RBI = *ST.getRegBankInfo();
switch (cast(MI).getIntrinsicID()) {
- case Intrinsic::trap: {
- MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
- MI.eraseFromParent();
- return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
- }
case Intrinsic::vacopy: {
MachinePointerInfo MPO;
LLT PtrTy = LLT::pointer(0, 32);
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 5738f86e7e9f..3103992a86c0 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -77,8 +77,6 @@ private:
MachineRegisterInfo &MRI) const;
bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
- bool selectIntrinsicWithSideEffects(MachineInstr &MI, MachineIRBuilder &MIB,
- MachineRegisterInfo &MRI) const;
void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
MachineIRBuilder &MIB) const;
bool selectMergeValues(MachineInstr &MI, MachineIRBuilder &MIB,
@@ -686,8 +684,6 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return selectSelect(MI, MIB, MRI);
case TargetOpcode::G_FCMP:
return selectFPCompare(MI, MIB, MRI);
- case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
- return selectIntrinsicWithSideEffects(MI, MIB, MRI);
case TargetOpcode::G_FENCE: {
AtomicOrdering FenceOrdering =
static_cast(MI.getOperand(0).getImm());
@@ -1255,29 +1251,6 @@ bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
return true;
}
-bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
- MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
- assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
- "Unexpected opcode");
- // Find the intrinsic ID.
- unsigned IntrinID = cast(MI).getIntrinsicID();
-
- // Select the instruction.
- switch (IntrinID) {
- default:
- return false;
- case Intrinsic::trap:
- MIB.buildInstr(RISCV::UNIMP, {}, {});
- break;
- case Intrinsic::debugtrap:
- MIB.buildInstr(RISCV::EBREAK, {}, {});
- break;
- }
-
- MI.eraseFromParent();
- return true;
-}
-
void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
SyncScope::ID FenceSSID,
MachineIRBuilder &MIB) const {
diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index 8e0f61a85566..9be3812300af 100644
--- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
@@ -119,8 +119,6 @@ private:
MachineFunction &MF) const;
bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
- bool selectIntrinsicWSideEffects(MachineInstr &I, MachineRegisterInfo &MRI,
- MachineFunction &MF) const;
// emit insert subreg instruction and insert it before MachineInstr &I
bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
@@ -434,8 +432,6 @@ bool X86InstructionSelector::select(MachineInstr &I) {
return selectMulDivRem(I, MRI, MF);
case TargetOpcode::G_SELECT:
return selectSelect(I, MRI, MF);
- case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
- return selectIntrinsicWSideEffects(I, MRI, MF);
}
return false;
@@ -1834,21 +1830,6 @@ bool X86InstructionSelector::selectSelect(MachineInstr &I,
return true;
}
-bool X86InstructionSelector::selectIntrinsicWSideEffects(
- MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const {
-
- assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
- "unexpected instruction");
-
- if (I.getOperand(0).getIntrinsicID() != Intrinsic::trap)
- return false;
-
- BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TRAP));
-
- I.eraseFromParent();
- return true;
-}
-
InstructionSelector *
llvm::createX86InstructionSelector(const X86TargetMachine &TM,
X86Subtarget &Subtarget,
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll
index fe9427d2678a..edae903fae84 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll
@@ -6,7 +6,7 @@ declare void @llvm.trap()
define void @unreachable() {
; CHECK-LABEL: name: unreachable
; CHECK: bb.1 (%ir-block.0):
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
unreachable
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll
index 5662de4cbdca..f7550ceb2799 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll
@@ -48,7 +48,7 @@ define void @bar() personality ptr @__gxx_personality_v0 {
; CHECK-NEXT: $x0 = COPY [[LOAD]](p0)
; CHECK-NEXT: BL @_Unwind_Resume, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
%exn.slot = alloca ptr
%ehselector.slot = alloca i32
%1 = invoke i32 @foo(i32 42) to label %continue unwind label %cleanup
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index c9e5f8924f8a..ac3c47c8001d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -752,6 +752,15 @@
# DEBUG-NEXT: G_BZERO (opcode {{[0-9]+}}): 2 type indices, 1 imm index
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_TRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_DEBUGTRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_UBSANTRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_VECREDUCE_SEQ_FADD (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir
index ad66fa5623e3..25ecce4dd92b 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir
@@ -26,7 +26,7 @@ body: |
; CHECK-LABEL: name: foo
; CHECK: BRK 1
; CHECK: RET_ReallyLR
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
RET_ReallyLR
...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir b/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir
index f4366fb7888e..b242c68e3b07 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir
@@ -26,7 +26,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
@@ -48,7 +48,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%8:_(s32) = G_ZEXT %6(s8)
@@ -80,7 +80,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
@@ -102,7 +102,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%8:_(s32) = G_ZEXT %6(s16)
@@ -134,7 +134,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: liveins: $x2
@@ -165,7 +165,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
liveins: $x2
@@ -206,7 +206,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
@@ -228,7 +228,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%8:_(s32) = G_ANYEXT %6(s16)
@@ -261,7 +261,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
@@ -284,7 +284,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%8:_(s32) = G_ZEXT %6(s16)
@@ -317,7 +317,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
@@ -340,7 +340,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%8:_(s32) = G_ZEXT %6(s16)
@@ -377,7 +377,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: liveins: $x2
@@ -410,7 +410,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
liveins: $x2
@@ -512,7 +512,7 @@ body: |
; CHECK-NEXT: bb.2:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.3:
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s16)
@@ -544,7 +544,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%9:_(s32) = G_ZEXT %6(s16)
@@ -577,7 +577,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8)
@@ -601,7 +601,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%9:_(s32) = G_ZEXT %7(s8)
@@ -634,7 +634,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8)
@@ -658,7 +658,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%9:_(s32) = G_ZEXT %7(s8)
@@ -692,7 +692,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8)
@@ -717,7 +717,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%10:_(s32) = G_ZEXT %8(s8)
@@ -783,7 +783,7 @@ body: |
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDO]](s16)
@@ -804,7 +804,7 @@ body: |
bb.2:
successors:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.3:
%6:_(s32) = G_ANYEXT %4(s16)
@@ -839,7 +839,7 @@ body: |
; CHECK-NEXT: RET_ReallyLR implicit $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
- ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; CHECK-NEXT: G_TRAP
bb.1:
successors: %bb.2(0x7ffff800), %bb.3(0x00000800)
liveins: $w0, $w1
@@ -860,6 +860,6 @@ body: |
RET_ReallyLR implicit $w0
bb.3:
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
...
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir
index b4bc64812b53..305eca792cfb 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir
@@ -24,7 +24,7 @@ body: |
bb.0:
%0:_(s8) = G_CONSTANT i8 0
%1:_(p1) = G_CONSTANT i64 0
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
bb.1:
G_STORE %0, %1 :: (store 1, addrspace 1)
@@ -55,7 +55,7 @@ body: |
; GCN-NEXT: S_ENDPGM 0
bb.0:
%0:_(s8) = G_CONSTANT i8 0
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
%1:_(p1) = G_CONSTANT i64 0
bb.1:
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/trap.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/trap.mir
similarity index 55%
rename from llvm/test/CodeGen/Mips/GlobalISel/legalizer/trap.mir
rename to llvm/test/CodeGen/Mips/GlobalISel/instruction-select/trap.mir
index 64388933fda8..dc99ce8d7a09 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/trap.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/trap.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
--- |
declare void @llvm.trap()
@@ -9,12 +9,15 @@
---
name: f
alignment: 4
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
body: |
bb.1 (%ir-block.0):
; MIPS32-LABEL: name: f
; MIPS32: TRAP
- ; MIPS32: RetRA
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ ; MIPS32-NEXT: RetRA
+ G_TRAP
RetRA
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir
index 11789a030e6f..5f52030fc170 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir
@@ -14,7 +14,7 @@ body: |
; CHECK-LABEL: name: test_trap
; CHECK: UNIMP
; CHECK-NEXT: PseudoRET
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
PseudoRET
...
@@ -28,7 +28,7 @@ body: |
; CHECK-LABEL: name: test_debugtrap
; CHECK: EBREAK
; CHECK-NEXT: PseudoRET
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.debugtrap)
+ G_DEBUGTRAP
PseudoRET
...
diff --git a/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir b/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir
index ea548c296dca..20b8b671ac5a 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir
+++ b/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir
@@ -23,6 +23,6 @@ body: |
bb.1 (%ir-block.0):
; CHECK-LABEL: name: trap
; CHECK: TRAP
- G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
+ G_TRAP
...
diff --git a/llvm/test/CodeGen/X86/isel-traps.ll b/llvm/test/CodeGen/X86/isel-traps.ll
new file mode 100644
index 000000000000..c207387166a6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/isel-traps.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,X64
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,X64
+; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,GISEL-X64
+; RUN: llc < %s -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,X86
+; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,X86
+; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,GISEL-X86
+
+declare void @llvm.trap()
+
+define void @test_trap() {
+; ALL-LABEL: test_trap:
+; ALL: # %bb.0:
+; ALL-NEXT: ud2
+; ALL-NEXT: ret{{[l|q]}}
+ tail call void @llvm.trap()
+ ret void
+}
+
+define void @test_debugtrap() {
+; ALL-LABEL: test_debugtrap:
+; ALL: # %bb.0:
+; ALL-NEXT: int3
+; ALL-NEXT: ret{{[l|q]}}
+ tail call void @llvm.debugtrap()
+ ret void
+}
+
+define void @test_ubsantrap() {
+; ALL-LABEL: test_ubsantrap:
+; ALL: # %bb.0:
+; ALL-NEXT: ud1l 12(%eax), %eax
+; ALL-NEXT: ret{{[l|q]}}
+ call void @llvm.ubsantrap(i8 12)
+ ret void
+}
+
+define void @test_ubsantrap_custom() nounwind {
+; X64-LABEL: test_ubsantrap_custom:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: movl $42, %edi
+; X64-NEXT: callq guide@PLT
+; X64-NEXT: popq %rax
+; X64-NEXT: retq
+;
+; GISEL-X64-LABEL: test_ubsantrap_custom:
+; GISEL-X64: # %bb.0:
+; GISEL-X64-NEXT: pushq %rax
+; GISEL-X64-NEXT: movl $42, %edi
+; GISEL-X64-NEXT: callq guide
+; GISEL-X64-NEXT: popq %rax
+; GISEL-X64-NEXT: retq
+;
+; X86-LABEL: test_ubsantrap_custom:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: movl $42, (%esp)
+; X86-NEXT: calll guide
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+;
+; GISEL-X86-LABEL: test_ubsantrap_custom:
+; GISEL-X86: # %bb.0:
+; GISEL-X86-NEXT: subl $12, %esp
+; GISEL-X86-NEXT: movl $42, %eax
+; GISEL-X86-NEXT: movl %eax, (%esp)
+; GISEL-X86-NEXT: calll guide
+; GISEL-X86-NEXT: addl $12, %esp
+; GISEL-X86-NEXT: retl
+ call void @llvm.ubsantrap(i8 42) "trap-func-name"="guide"
+ ret void
+}
diff --git a/llvm/test/MachineVerifier/test_g_ubsantrap.mir b/llvm/test/MachineVerifier/test_g_ubsantrap.mir
new file mode 100644
index 000000000000..d2b219d8650a
--- /dev/null
+++ b/llvm/test/MachineVerifier/test_g_ubsantrap.mir
@@ -0,0 +1,18 @@
+# RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+---
+name: test_ubsantrap
+tracksRegLiveness: true
+liveins:
+body: |
+ bb.0:
+
+ ; CHECK: Crash kind must be 8 bit wide
+ G_UBSANTRAP 4096
+
+ ; CHECK: Crash kind must be an immediate
+ %5:_(s32) = IMPLICIT_DEF
+ G_UBSANTRAP %5
+
+...
--
GitLab
From f886dfed3ae6cf70827cedc8d8aefde6250a239b Mon Sep 17 00:00:00 2001
From: Nikolas Klauser
Date: Sat, 23 Mar 2024 13:54:35 +0100
Subject: [PATCH 019/879] [libc++] Don't push and pop extensions diagnostics
when using clang modules (#85917)
Clang modules take a significant compile time hit when pushing and
popping diagnostics. Since all the headers are marked as system headers
in the modulemap, we can simply disable this pushing and popping when
building with clang modules.
---
libcxx/include/__config | 34 +++++++++++++++++++++++-----------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 132cace3d5b2..af44af203e7c 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -838,21 +838,33 @@ typedef __char32_t char32_t;
# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions")
#endif
+// Clang modules take a significant compile time hit when pushing and popping diagnostics.
+// Since all the headers are marked as system headers in the modulemap, we can simply disable this
+// pushing and popping when building with clang modules.
+# if !__has_feature(modules)
+# define _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \
+ _LIBCPP_DIAGNOSTIC_PUSH \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++23-extensions")
+# define _LIBCPP_POP_EXTENSION_DIAGNOSTICS _LIBCPP_DIAGNOSTIC_POP
+# else
+# define _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS
+# define _LIBCPP_POP_EXTENSION_DIAGNOSTICS
+# endif
+
// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect.
// clang-format off
-# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DIAGNOSTIC_PUSH \
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
- _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
- _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \
+# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \
namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \
inline namespace _LIBCPP_ABI_NAMESPACE {
-# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_DIAGNOSTIC_POP
+# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_POP_EXTENSION_DIAGNOSTICS
# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD \
inline namespace __fs { namespace filesystem {
--
GitLab
From 57146daeaaf366050dc913db910fcc2995a3e06d Mon Sep 17 00:00:00 2001
From: Harvin Iriawan <25712785+harviniriawan@users.noreply.github.com>
Date: Sat, 23 Mar 2024 12:56:25 +0000
Subject: [PATCH 020/879] [CodeGen] Update for scalable MemoryType in MMO
(#70452)
Remove getSizeOrUnknown call when MachineMemOperand is created. For Scalable
TypeSize, the MemoryType created becomes a scalable_vector.
2 MMOs that have scalable memory access can then use the updated BasicAA that
understands scalable LocationSize.
Original Patch by Harvin Iriawan
Co-authored-by: David Green
---
llvm/include/llvm/Analysis/MemoryLocation.h | 7 ---
llvm/include/llvm/CodeGen/MachineFunction.h | 5 +-
llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp | 34 +++++++++----
llvm/lib/CodeGen/MachineInstr.cpp | 37 ++++++++++----
llvm/lib/CodeGen/MachineOperand.cpp | 13 ++---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 51 ++++++++++++-------
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 22 ++++----
.../SelectionDAGAddressAnalysis.cpp | 2 -
.../SelectionDAG/SelectionDAGBuilder.cpp | 3 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 5 +-
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 22 ++++++--
llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll | 6 +--
.../alloca-load-store-scalable-array.ll | 36 ++++++-------
.../alloca-load-store-scalable-struct.ll | 12 ++---
.../rvv/alloca-load-store-scalable-array.ll | 12 ++---
.../rvv/alloca-load-store-scalable-struct.ll | 8 +--
.../RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll | 8 +--
17 files changed, 165 insertions(+), 118 deletions(-)
diff --git a/llvm/include/llvm/Analysis/MemoryLocation.h b/llvm/include/llvm/Analysis/MemoryLocation.h
index 830eed5d60ee..7d896c44f467 100644
--- a/llvm/include/llvm/Analysis/MemoryLocation.h
+++ b/llvm/include/llvm/Analysis/MemoryLocation.h
@@ -297,13 +297,6 @@ public:
return MemoryLocation(Ptr, LocationSize::beforeOrAfterPointer(), AATags);
}
- // Return the exact size if the exact size is known at compiletime,
- // otherwise return LocationSize::beforeOrAfterPointer().
- static LocationSize getSizeOrUnknown(const TypeSize &T) {
- return T.isScalable() ? LocationSize::beforeOrAfterPointer()
- : LocationSize::precise(T.getFixedValue());
- }
-
MemoryLocation() : Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()) {}
explicit MemoryLocation(const Value *Ptr, LocationSize Size,
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index dfbf7a1e7aae..c2bff2794493 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -1058,8 +1058,9 @@ public:
int64_t Offset, LocationSize Size) {
return getMachineMemOperand(
MMO, Offset,
- !Size.hasValue() || Size.isScalable()
- ? LLT()
+ !Size.hasValue() ? LLT()
+ : Size.isScalable()
+ ? LLT::scalable_vector(1, 8 * Size.getValue().getKnownMinValue())
: LLT::scalar(8 * Size.getValue().getKnownMinValue()));
}
MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO,
diff --git a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
index 9fc8ecd60b03..fb9656c09ca3 100644
--- a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
@@ -128,14 +128,14 @@ bool GISelAddressing::aliasIsKnownForLoadStore(const MachineInstr &MI1,
// vector objects on the stack.
// BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the
// following situations arise:
- if (PtrDiff >= 0 && Size1.hasValue()) {
+ if (PtrDiff >= 0 && Size1.hasValue() && !Size1.isScalable()) {
// [----BasePtr0----]
// [---BasePtr1--]
// ========PtrDiff========>
IsAlias = !((int64_t)Size1.getValue() <= PtrDiff);
return true;
}
- if (PtrDiff < 0 && Size2.hasValue()) {
+ if (PtrDiff < 0 && Size2.hasValue() && !Size2.isScalable()) {
// [----BasePtr0----]
// [---BasePtr1--]
// =====(-PtrDiff)====>
@@ -248,10 +248,20 @@ bool GISelAddressing::instMayAlias(const MachineInstr &MI,
return false;
}
+ // If NumBytes is scalable and offset is not 0, conservatively return may
+ // alias
+ if ((MUC0.NumBytes.isScalable() && MUC0.Offset != 0) ||
+ (MUC1.NumBytes.isScalable() && MUC1.Offset != 0))
+ return true;
+
+ const bool BothNotScalable =
+ !MUC0.NumBytes.isScalable() && !MUC1.NumBytes.isScalable();
+
// Try to prove that there is aliasing, or that there is no aliasing. Either
// way, we can return now. If nothing can be proved, proceed with more tests.
bool IsAlias;
- if (GISelAddressing::aliasIsKnownForLoadStore(MI, Other, IsAlias, MRI))
+ if (BothNotScalable &&
+ GISelAddressing::aliasIsKnownForLoadStore(MI, Other, IsAlias, MRI))
return IsAlias;
// The following all rely on MMO0 and MMO1 being valid.
@@ -267,12 +277,18 @@ bool GISelAddressing::instMayAlias(const MachineInstr &MI,
Size1.hasValue()) {
// Use alias analysis information.
int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
- int64_t Overlap0 = Size0.getValue() + SrcValOffset0 - MinOffset;
- int64_t Overlap1 = Size1.getValue() + SrcValOffset1 - MinOffset;
- if (AA->isNoAlias(MemoryLocation(MUC0.MMO->getValue(), Overlap0,
- MUC0.MMO->getAAInfo()),
- MemoryLocation(MUC1.MMO->getValue(), Overlap1,
- MUC1.MMO->getAAInfo())))
+ int64_t Overlap0 =
+ Size0.getValue().getKnownMinValue() + SrcValOffset0 - MinOffset;
+ int64_t Overlap1 =
+ Size1.getValue().getKnownMinValue() + SrcValOffset1 - MinOffset;
+ LocationSize Loc0 =
+ Size0.isScalable() ? Size0 : LocationSize::precise(Overlap0);
+ LocationSize Loc1 =
+ Size1.isScalable() ? Size1 : LocationSize::precise(Overlap1);
+
+ if (AA->isNoAlias(
+ MemoryLocation(MUC0.MMO->getValue(), Loc0, MUC0.MMO->getAAInfo()),
+ MemoryLocation(MUC1.MMO->getValue(), Loc1, MUC1.MMO->getAAInfo())))
return false;
}
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index fe2f9ccd33a3..8102bb971ba6 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -1306,6 +1306,7 @@ static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA,
LocationSize WidthB = MMOb->getSize();
bool KnownWidthA = WidthA.hasValue();
bool KnownWidthB = WidthB.hasValue();
+ bool BothMMONonScalable = !WidthA.isScalable() && !WidthB.isScalable();
const Value *ValA = MMOa->getValue();
const Value *ValB = MMOb->getValue();
@@ -1321,12 +1322,14 @@ static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA,
SameVal = true;
}
- if (SameVal) {
+ if (SameVal && BothMMONonScalable) {
if (!KnownWidthA || !KnownWidthB)
return true;
int64_t MaxOffset = std::max(OffsetA, OffsetB);
- LocationSize LowWidth = (MinOffset == OffsetA) ? WidthA : WidthB;
- return (MinOffset + (int)LowWidth.getValue() > MaxOffset);
+ int64_t LowWidth = (MinOffset == OffsetA)
+ ? WidthA.getValue().getKnownMinValue()
+ : WidthB.getValue().getKnownMinValue();
+ return (MinOffset + LowWidth > MaxOffset);
}
if (!AA)
@@ -1338,15 +1341,29 @@ static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA,
assert((OffsetA >= 0) && "Negative MachineMemOperand offset");
assert((OffsetB >= 0) && "Negative MachineMemOperand offset");
- int64_t OverlapA = KnownWidthA ? WidthA.getValue() + OffsetA - MinOffset
- : MemoryLocation::UnknownSize;
- int64_t OverlapB = KnownWidthB ? WidthB.getValue() + OffsetB - MinOffset
- : MemoryLocation::UnknownSize;
+ // If Scalable Location Size has non-zero offset, Width + Offset does not work
+ // at the moment
+ if ((WidthA.isScalable() && OffsetA > 0) ||
+ (WidthB.isScalable() && OffsetB > 0))
+ return true;
+
+ int64_t OverlapA =
+ KnownWidthA ? WidthA.getValue().getKnownMinValue() + OffsetA - MinOffset
+ : MemoryLocation::UnknownSize;
+ int64_t OverlapB =
+ KnownWidthB ? WidthB.getValue().getKnownMinValue() + OffsetB - MinOffset
+ : MemoryLocation::UnknownSize;
+
+ LocationSize LocA = (WidthA.isScalable() || !KnownWidthA)
+ ? WidthA
+ : LocationSize::precise(OverlapA);
+ LocationSize LocB = (WidthB.isScalable() || !KnownWidthB)
+ ? WidthB
+ : LocationSize::precise(OverlapB);
return !AA->isNoAlias(
- MemoryLocation(ValA, OverlapA, UseTBAA ? MMOa->getAAInfo() : AAMDNodes()),
- MemoryLocation(ValB, OverlapB,
- UseTBAA ? MMOb->getAAInfo() : AAMDNodes()));
+ MemoryLocation(ValA, LocA, UseTBAA ? MMOa->getAAInfo() : AAMDNodes()),
+ MemoryLocation(ValB, LocB, UseTBAA ? MMOb->getAAInfo() : AAMDNodes()));
}
bool MachineInstr::mayAlias(AAResults *AA, const MachineInstr &Other,
diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp
index 937ca539513a..ace05902d5df 100644
--- a/llvm/lib/CodeGen/MachineOperand.cpp
+++ b/llvm/lib/CodeGen/MachineOperand.cpp
@@ -1107,12 +1107,13 @@ MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags F,
const MDNode *Ranges, SyncScope::ID SSID,
AtomicOrdering Ordering,
AtomicOrdering FailureOrdering)
- : MachineMemOperand(ptrinfo, F,
- !TS.hasValue() || TS.isScalable()
- ? LLT()
- : LLT::scalar(8 * TS.getValue().getKnownMinValue()),
- BaseAlignment, AAInfo, Ranges, SSID, Ordering,
- FailureOrdering) {}
+ : MachineMemOperand(
+ ptrinfo, F,
+ !TS.hasValue() ? LLT()
+ : TS.isScalable()
+ ? LLT::scalable_vector(1, 8 * TS.getValue().getKnownMinValue())
+ : LLT::scalar(8 * TS.getValue().getKnownMinValue()),
+ BaseAlignment, AAInfo, Ranges, SSID, Ordering, FailureOrdering) {}
void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) {
// The Value and Offset may differ due to CSE. But the flags and size
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index dcd0310734ad..e27a8bb8fdac 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -24200,7 +24200,7 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG) {
// TODO: Use "BaseIndexOffset" to make this more effective.
SDValue NewAddr = DAG.getMemBasePlusOffset(Ld->getBasePtr(), Offset, DL);
- LocationSize StoreSize = MemoryLocation::getSizeOrUnknown(VT.getStoreSize());
+ LocationSize StoreSize = LocationSize::precise(VT.getStoreSize());
MachineFunction &MF = DAG.getMachineFunction();
MachineMemOperand *MMO;
if (Offset.isScalable()) {
@@ -27845,14 +27845,10 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const {
: (LSN->getAddressingMode() == ISD::PRE_DEC)
? -1 * C->getSExtValue()
: 0;
- LocationSize Size =
- MemoryLocation::getSizeOrUnknown(LSN->getMemoryVT().getStoreSize());
- return {LSN->isVolatile(),
- LSN->isAtomic(),
- LSN->getBasePtr(),
- Offset /*base offset*/,
- Size,
- LSN->getMemOperand()};
+ TypeSize Size = LSN->getMemoryVT().getStoreSize();
+ return {LSN->isVolatile(), LSN->isAtomic(),
+ LSN->getBasePtr(), Offset /*base offset*/,
+ LocationSize::precise(Size), LSN->getMemOperand()};
}
if (const auto *LN = cast(N))
return {false /*isVolatile*/,
@@ -27894,6 +27890,13 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const {
return false;
}
+ // If NumBytes is scalable and offset is not 0, conservatively return may
+ // alias
+ if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
+ MUC0.Offset != 0) ||
+ (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
+ MUC1.Offset != 0))
+ return true;
// Try to prove that there is aliasing, or that there is no aliasing. Either
// way, we can return now. If nothing can be proved, proceed with more tests.
bool IsAlias;
@@ -27924,18 +27927,22 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const {
Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
LocationSize Size0 = MUC0.NumBytes;
LocationSize Size1 = MUC1.NumBytes;
+
if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
- Size0.hasValue() && Size1.hasValue() && Size0 == Size1 &&
- OrigAlignment0 > Size0.getValue() &&
- SrcValOffset0 % Size0.getValue() == 0 &&
- SrcValOffset1 % Size1.getValue() == 0) {
+ Size0.hasValue() && Size1.hasValue() && !Size0.isScalable() &&
+ !Size1.isScalable() && Size0 == Size1 &&
+ OrigAlignment0 > Size0.getValue().getKnownMinValue() &&
+ SrcValOffset0 % Size0.getValue().getKnownMinValue() == 0 &&
+ SrcValOffset1 % Size1.getValue().getKnownMinValue() == 0) {
int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.value();
int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.value();
// There is no overlap between these relatively aligned accesses of
// similar size. Return no alias.
- if ((OffAlign0 + (int64_t)Size0.getValue()) <= OffAlign1 ||
- (OffAlign1 + (int64_t)Size1.getValue()) <= OffAlign0)
+ if ((OffAlign0 + static_cast(
+ Size0.getValue().getKnownMinValue())) <= OffAlign1 ||
+ (OffAlign1 + static_cast(
+ Size1.getValue().getKnownMinValue())) <= OffAlign0)
return false;
}
@@ -27952,12 +27959,18 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const {
Size0.hasValue() && Size1.hasValue()) {
// Use alias analysis information.
int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
- int64_t Overlap0 = Size0.getValue() + SrcValOffset0 - MinOffset;
- int64_t Overlap1 = Size1.getValue() + SrcValOffset1 - MinOffset;
+ int64_t Overlap0 =
+ Size0.getValue().getKnownMinValue() + SrcValOffset0 - MinOffset;
+ int64_t Overlap1 =
+ Size1.getValue().getKnownMinValue() + SrcValOffset1 - MinOffset;
+ LocationSize Loc0 =
+ Size0.isScalable() ? Size0 : LocationSize::precise(Overlap0);
+ LocationSize Loc1 =
+ Size1.isScalable() ? Size1 : LocationSize::precise(Overlap1);
if (AA->isNoAlias(
- MemoryLocation(MUC0.MMO->getValue(), Overlap0,
+ MemoryLocation(MUC0.MMO->getValue(), Loc0,
UseTBAA ? MUC0.MMO->getAAInfo() : AAMDNodes()),
- MemoryLocation(MUC1.MMO->getValue(), Overlap1,
+ MemoryLocation(MUC1.MMO->getValue(), Loc1,
UseTBAA ? MUC1.MMO->getAAInfo() : AAMDNodes())))
return false;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index e2c07e7cb997..0ab5142ab816 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -8406,9 +8406,7 @@ SDValue SelectionDAG::getMemIntrinsicNode(
EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment,
MachineMemOperand::Flags Flags, LocationSize Size,
const AAMDNodes &AAInfo) {
- if (Size.hasValue() && MemVT.isScalableVector())
- Size = LocationSize::beforeOrAfterPointer();
- else if (Size.hasValue() && !Size.getValue())
+ if (Size.hasValue() && !Size.getValue())
Size = LocationSize::precise(MemVT.getStoreSize());
MachineFunction &MF = getMachineFunction();
@@ -8571,7 +8569,7 @@ SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
if (PtrInfo.V.isNull())
PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr, Offset);
- LocationSize Size = MemoryLocation::getSizeOrUnknown(MemVT.getStoreSize());
+ LocationSize Size = LocationSize::precise(MemVT.getStoreSize());
MachineFunction &MF = getMachineFunction();
MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size,
Alignment, AAInfo, Ranges);
@@ -8692,8 +8690,7 @@ SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr);
MachineFunction &MF = getMachineFunction();
- LocationSize Size =
- MemoryLocation::getSizeOrUnknown(Val.getValueType().getStoreSize());
+ LocationSize Size = LocationSize::precise(Val.getValueType().getStoreSize());
MachineMemOperand *MMO =
MF.getMachineMemOperand(PtrInfo, MMOFlags, Size, Alignment, AAInfo);
return getStore(Chain, dl, Val, Ptr, MMO);
@@ -8746,8 +8743,8 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val,
MachineFunction &MF = getMachineFunction();
MachineMemOperand *MMO = MF.getMachineMemOperand(
- PtrInfo, MMOFlags, MemoryLocation::getSizeOrUnknown(SVT.getStoreSize()),
- Alignment, AAInfo);
+ PtrInfo, MMOFlags, LocationSize::precise(SVT.getStoreSize()), Alignment,
+ AAInfo);
return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO);
}
@@ -8841,7 +8838,7 @@ SDValue SelectionDAG::getLoadVP(
if (PtrInfo.V.isNull())
PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr, Offset);
- LocationSize Size = MemoryLocation::getSizeOrUnknown(MemVT.getStoreSize());
+ LocationSize Size = LocationSize::precise(MemVT.getStoreSize());
MachineFunction &MF = getMachineFunction();
MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size,
Alignment, AAInfo, Ranges);
@@ -8994,8 +8991,8 @@ SDValue SelectionDAG::getTruncStoreVP(SDValue Chain, const SDLoc &dl,
MachineFunction &MF = getMachineFunction();
MachineMemOperand *MMO = MF.getMachineMemOperand(
- PtrInfo, MMOFlags, MemoryLocation::getSizeOrUnknown(SVT.getStoreSize()),
- Alignment, AAInfo);
+ PtrInfo, MMOFlags, LocationSize::precise(SVT.getStoreSize()), Alignment,
+ AAInfo);
return getTruncStoreVP(Chain, dl, Val, Ptr, Mask, EVL, SVT, MMO,
IsCompressing);
}
@@ -11734,10 +11731,9 @@ MemSDNode::MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
// We check here that the size of the memory operand fits within the size of
// the MMO. This is because the MMO might indicate only a possible address
// range instead of specifying the affected memory addresses precisely.
- // TODO: Make MachineMemOperands aware of scalable vectors.
assert(
(!MMO->getType().isValid() ||
- memvt.getStoreSize().getKnownMinValue() <= MMO->getSize().getValue()) &&
+ TypeSize::isKnownLE(memvt.getStoreSize(), MMO->getSize().getValue())) &&
"Size mismatch!");
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp
index 9670c3ac8430..f2ab88851b78 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp
@@ -106,8 +106,6 @@ bool BaseIndexOffset::computeAliasing(const SDNode *Op0,
int64_t PtrDiff;
if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) {
// If the size of memory access is unknown, do not use it to analysis.
- // One example of unknown size memory access is to load/store scalable
- // vector objects on the stack.
// BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the
// following situations arise:
if (PtrDiff >= 0 && NumBytes0.hasValue() && !NumBytes0.isScalable()) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 84df98b8a613..ae6bd7e938e8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4962,7 +4962,8 @@ void SelectionDAGBuilder::visitMaskedGather(const CallInst &I) {
unsigned AS = Ptr->getType()->getScalarType()->getPointerAddressSpace();
MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
MachinePointerInfo(AS), MachineMemOperand::MOLoad,
- LocationSize::beforeOrAfterPointer(), Alignment, I.getAAMetadata(), Ranges);
+ LocationSize::beforeOrAfterPointer(), Alignment, I.getAAMetadata(),
+ Ranges);
if (!UniformBase) {
Base = DAG.getConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout()));
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 02943b8a4ab1..d0c5e6b99e9e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -2687,10 +2687,7 @@ bool AArch64InstrInfo::getMemOperandsWithOffsetWidth(
return false;
// The maximum vscale is 16 under AArch64, return the maximal extent for the
// vector.
- Width = WidthN.isScalable()
- ? WidthN.getKnownMinValue() * AArch64::SVEMaxBitsPerVector /
- AArch64::SVEBitsPerBlock
- : WidthN.getKnownMinValue();
+ Width = LocationSize::precise(WidthN);
BaseOps.push_back(BaseOp);
return true;
}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 5a2fb0239e0a..5214595485ca 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -10364,9 +10364,15 @@ RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(SDValue Op,
RISCVTargetLowering::computeVLMAXBounds(ContainerVT, Subtarget);
if (MinVLMAX == MaxVLMAX && MinVLMAX == VT.getVectorNumElements() &&
getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
+ MachineMemOperand *MMO = Load->getMemOperand();
+ MachineFunction &MF = DAG.getMachineFunction();
+ MMO = MF.getMachineMemOperand(
+ MMO, MMO->getPointerInfo(),
+ MMO->getMemoryType().isValid()
+ ? LLT::scalable_vector(1, MMO->getMemoryType().getSizeInBits())
+ : MMO->getMemoryType());
SDValue NewLoad =
- DAG.getLoad(ContainerVT, DL, Load->getChain(), Load->getBasePtr(),
- Load->getMemOperand());
+ DAG.getLoad(ContainerVT, DL, Load->getChain(), Load->getBasePtr(), MMO);
SDValue Result = convertFromScalableVector(VT, NewLoad, DAG, Subtarget);
return DAG.getMergeValues({Result, NewLoad.getValue(1)}, DL);
}
@@ -10424,9 +10430,17 @@ RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(SDValue Op,
const auto [MinVLMAX, MaxVLMAX] =
RISCVTargetLowering::computeVLMAXBounds(ContainerVT, Subtarget);
if (MinVLMAX == MaxVLMAX && MinVLMAX == VT.getVectorNumElements() &&
- getLMUL1VT(ContainerVT).bitsLE(ContainerVT))
+ getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
+ MachineMemOperand *MMO = Store->getMemOperand();
+ MachineFunction &MF = DAG.getMachineFunction();
+ MMO = MF.getMachineMemOperand(
+ MMO, MMO->getPointerInfo(),
+ MMO->getMemoryType().isValid()
+ ? LLT::scalable_vector(1, MMO->getMemoryType().getSizeInBits())
+ : MMO->getMemoryType());
return DAG.getStore(Store->getChain(), DL, NewValue, Store->getBasePtr(),
- Store->getMemOperand());
+ MMO);
+ }
SDValue VL = getVLOp(VT.getVectorNumElements(), ContainerVT, DL, DAG,
Subtarget);
diff --git a/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll b/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll
index 58299696e78f..d4d803a91cfa 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll
@@ -3,7 +3,7 @@
define void @UphPNR(target("aarch64.svcount") %predcnt) {
entry:
; CHECK: %0:ppr = COPY $p0
-; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store unknown-size into %ir.predcnt.addr, align 2)
+; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store () into %ir.predcnt.addr)
; CHECK: %1:pnr_p8to15 = COPY %0
; CHECK: INLINEASM &"ld1w {z0.s,z1.s,z2.s,z3.s}, $0/z, [x10]", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:PNR_p8to15 */, %1
; CHECK: RET_ReallyLR
@@ -17,7 +17,7 @@ entry:
define void @UpaPNR(target("aarch64.svcount") %predcnt) {
entry:
; CHECK: %0:ppr = COPY $p0
-; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store unknown-size into %ir.predcnt.addr, align 2)
+; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store () into %ir.predcnt.addr)
; CHECK: %1:pnr = COPY %0
; CHECK: INLINEASM &"ld1w {z0.s,z1.s,z2.s,z3.s}, $0/z, [x10]", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:PNR */, %1
; CHECK: RET_ReallyLR
@@ -31,7 +31,7 @@ entry:
define void @UplPNR(target("aarch64.svcount") %predcnt) {
entry:
; CHECK: %0:ppr = COPY $p0
-; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store unknown-size into %ir.predcnt.addr, align 2)
+; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store () into %ir.predcnt.addr)
; CHECK: %1:pnr_3b = COPY %0
; CHECK: INLINEASM &"fadd z0.h, $0/m, z0.h, #0.5", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:PNR_3b */, %1
; CHECK: RET_ReallyLR
diff --git a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll
index 9a4e01a29ecb..7244ac949ab8 100644
--- a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll
+++ b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll
@@ -14,12 +14,12 @@ define void @array_1D(ptr %addr) #0 {
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: ptrue p0.d
-; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0, #2, mul vl]
-; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #1, mul vl]
-; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0]
-; CHECK-NEXT: st1d { z0.d }, p0, [sp, #2, mul vl]
-; CHECK-NEXT: st1d { z1.d }, p0, [sp, #1, mul vl]
-; CHECK-NEXT: st1d { z2.d }, p0, [sp]
+; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]
+; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #2, mul vl]
+; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0, #1, mul vl]
+; CHECK-NEXT: st1d { z0.d }, p0, [sp]
+; CHECK-NEXT: st1d { z1.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT: st1d { z2.d }, p0, [sp, #1, mul vl]
; CHECK-NEXT: addvl sp, sp, #3
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
; CHECK-NEXT: ret
@@ -81,18 +81,18 @@ define void @array_2D(ptr %addr) #0 {
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x30, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 48 * VG
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: ptrue p0.d
-; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0, #5, mul vl]
-; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #4, mul vl]
-; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0]
-; CHECK-NEXT: ld1d { z3.d }, p0/z, [x0, #3, mul vl]
-; CHECK-NEXT: ld1d { z4.d }, p0/z, [x0, #1, mul vl]
-; CHECK-NEXT: ld1d { z5.d }, p0/z, [x0, #2, mul vl]
-; CHECK-NEXT: st1d { z0.d }, p0, [sp, #5, mul vl]
-; CHECK-NEXT: st1d { z1.d }, p0, [sp, #4, mul vl]
-; CHECK-NEXT: st1d { z3.d }, p0, [sp, #3, mul vl]
-; CHECK-NEXT: st1d { z5.d }, p0, [sp, #2, mul vl]
-; CHECK-NEXT: st1d { z4.d }, p0, [sp, #1, mul vl]
-; CHECK-NEXT: st1d { z2.d }, p0, [sp]
+; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]
+; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #5, mul vl]
+; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0, #1, mul vl]
+; CHECK-NEXT: ld1d { z3.d }, p0/z, [x0, #4, mul vl]
+; CHECK-NEXT: ld1d { z4.d }, p0/z, [x0, #2, mul vl]
+; CHECK-NEXT: ld1d { z5.d }, p0/z, [x0, #3, mul vl]
+; CHECK-NEXT: st1d { z0.d }, p0, [sp]
+; CHECK-NEXT: st1d { z1.d }, p0, [sp, #5, mul vl]
+; CHECK-NEXT: st1d { z3.d }, p0, [sp, #4, mul vl]
+; CHECK-NEXT: st1d { z5.d }, p0, [sp, #3, mul vl]
+; CHECK-NEXT: st1d { z4.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT: st1d { z2.d }, p0, [sp, #1, mul vl]
; CHECK-NEXT: addvl sp, sp, #6
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll
index 7292d52aaf47..f03a6f018d34 100644
--- a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll
+++ b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll
@@ -13,12 +13,12 @@ define void @test(ptr %addr) #0 {
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: ptrue p0.d
-; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0, #2, mul vl]
-; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #1, mul vl]
-; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0]
-; CHECK-NEXT: st1d { z0.d }, p0, [sp, #2, mul vl]
-; CHECK-NEXT: st1d { z1.d }, p0, [sp, #1, mul vl]
-; CHECK-NEXT: st1d { z2.d }, p0, [sp]
+; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0]
+; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #2, mul vl]
+; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0, #1, mul vl]
+; CHECK-NEXT: st1d { z0.d }, p0, [sp]
+; CHECK-NEXT: st1d { z1.d }, p0, [sp, #2, mul vl]
+; CHECK-NEXT: st1d { z2.d }, p0, [sp, #1, mul vl]
; CHECK-NEXT: addvl sp, sp, #3
; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload
; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll
index 1d025a2f776f..1fe91c721f4d 100644
--- a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll
@@ -18,15 +18,15 @@ define void @test(ptr %addr) {
; CHECK-NEXT: add a2, a0, a1
; CHECK-NEXT: vl1re64.v v8, (a2)
; CHECK-NEXT: slli a2, a1, 1
-; CHECK-NEXT: add a3, a0, a2
-; CHECK-NEXT: vl1re64.v v9, (a3)
+; CHECK-NEXT: vl1re64.v v9, (a0)
+; CHECK-NEXT: add a0, a0, a2
; CHECK-NEXT: vl1re64.v v10, (a0)
; CHECK-NEXT: addi a0, sp, 16
+; CHECK-NEXT: vs1r.v v9, (a0)
; CHECK-NEXT: add a2, a0, a2
-; CHECK-NEXT: vs1r.v v9, (a2)
-; CHECK-NEXT: add a1, a0, a1
-; CHECK-NEXT: vs1r.v v8, (a1)
-; CHECK-NEXT: vs1r.v v10, (a0)
+; CHECK-NEXT: vs1r.v v10, (a2)
+; CHECK-NEXT: add a0, a0, a1
+; CHECK-NEXT: vs1r.v v8, (a0)
; CHECK-NEXT: csrrs a0, vlenb, zero
; CHECK-NEXT: slli a0, a0, 2
; CHECK-NEXT: add sp, sp, a0
diff --git a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll
index 64031f8a9359..a9a680d54d58 100644
--- a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll
@@ -16,13 +16,13 @@ define @test(ptr %addr, i64 %vl) {
; CHECK-NEXT: sub sp, sp, a2
; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x02, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 2 * vlenb
; CHECK-NEXT: csrrs a2, vlenb, zero
-; CHECK-NEXT: add a3, a0, a2
-; CHECK-NEXT: vl1re64.v v8, (a3)
+; CHECK-NEXT: vl1re64.v v8, (a0)
+; CHECK-NEXT: add a0, a0, a2
; CHECK-NEXT: vl1re64.v v9, (a0)
; CHECK-NEXT: addi a0, sp, 16
+; CHECK-NEXT: vs1r.v v8, (a0)
; CHECK-NEXT: add a2, a0, a2
-; CHECK-NEXT: vs1r.v v8, (a2)
-; CHECK-NEXT: vs1r.v v9, (a0)
+; CHECK-NEXT: vs1r.v v9, (a2)
; CHECK-NEXT: vl1re64.v v8, (a2)
; CHECK-NEXT: vl1re64.v v9, (a0)
; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, ma
diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll
index 0544204cce79..52bd15742ef4 100644
--- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll
@@ -16,8 +16,8 @@ define void @vpmerge_vpload_store( %passthru, ptr %p, ) into %ir.p)
; CHECK-NEXT: PseudoRET
%splat = insertelement poison, i1 -1, i32 0
%mask = shufflevector %splat, poison, zeroinitializer
@@ -37,8 +37,8 @@ define void @vpselect_vpload_store( %passthru, ptr %p, ) into %ir.p)
; CHECK-NEXT: PseudoRET
%splat = insertelement poison, i1 -1, i32 0
%mask = shufflevector %splat, poison, zeroinitializer
--
GitLab
From b68e2eba0bc8dd70b88f4271831139ee9b6ed25c Mon Sep 17 00:00:00 2001
From: Nikolas Klauser
Date: Sat, 23 Mar 2024 15:28:22 +0100
Subject: [PATCH 021/879] [libc++] Vectorize mismatch (#73255)
```
---------------------------------------------------
Benchmark old new
---------------------------------------------------
bm_mismatch/1 0.835 ns 2.37 ns
bm_mismatch/2 1.44 ns 2.60 ns
bm_mismatch/3 2.06 ns 2.83 ns
bm_mismatch/4 2.60 ns 3.29 ns
bm_mismatch/5 3.15 ns 3.77 ns
bm_mismatch/6 3.82 ns 4.17 ns
bm_mismatch/7 4.29 ns 4.52 ns
bm_mismatch/8 4.78 ns 4.86 ns
bm_mismatch/16 9.06 ns 7.54 ns
bm_mismatch/64 31.7 ns 19.1 ns
bm_mismatch/512 249 ns 8.16 ns
bm_mismatch/4096 1956 ns 44.2 ns
bm_mismatch/32768 15498 ns 501 ns
bm_mismatch/262144 123965 ns 4479 ns
bm_mismatch/1048576 495668 ns 21306 ns
bm_mismatch/1 0.710 ns 2.12 ns
bm_mismatch/2 1.03 ns 2.66 ns
bm_mismatch/3 1.29 ns 3.56 ns
bm_mismatch/4 1.68 ns 4.29 ns
bm_mismatch/5 1.96 ns 5.18 ns
bm_mismatch/6 2.59 ns 5.91 ns
bm_mismatch/7 2.86 ns 6.63 ns
bm_mismatch/8 3.19 ns 7.33 ns
bm_mismatch/16 5.48 ns 13.0 ns
bm_mismatch/64 16.6 ns 4.06 ns
bm_mismatch/512 130 ns 13.8 ns
bm_mismatch/4096 985 ns 93.8 ns
bm_mismatch/32768 7846 ns 1002 ns
bm_mismatch/262144 63217 ns 10637 ns
bm_mismatch/1048576 251782 ns 42471 ns
bm_mismatch/1 0.716 ns 1.91 ns
bm_mismatch/2 1.21 ns 2.49 ns
bm_mismatch/3 1.38 ns 3.46 ns
bm_mismatch/4 1.71 ns 4.04 ns
bm_mismatch/5 2.00 ns 4.98 ns
bm_mismatch/6 2.43 ns 5.67 ns
bm_mismatch/7 3.05 ns 6.38 ns
bm_mismatch/8 3.22 ns 7.09 ns
bm_mismatch/16 5.18 ns 12.8 ns
bm_mismatch/64 16.6 ns 5.28 ns
bm_mismatch/512 129 ns 25.2 ns
bm_mismatch/4096 1009 ns 201 ns
bm_mismatch/32768 7776 ns 2144 ns
bm_mismatch/262144 62371 ns 20551 ns
bm_mismatch/1048576 254750 ns 90097 ns
```
---
libcxx/benchmarks/CMakeLists.txt | 1 +
.../benchmarks/algorithms/mismatch.bench.cpp | 31 +++
libcxx/docs/ReleaseNotes/19.rst | 2 +
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__algorithm/mismatch.h | 82 ++++++-
libcxx/include/__algorithm/simd_utils.h | 123 ++++++++++
libcxx/include/__bit/bit_cast.h | 9 +
libcxx/include/__bit/countr.h | 13 +-
libcxx/include/libcxx.imp | 1 +
libcxx/include/module.modulemap | 6 +-
.../mismatch/mismatch.pass.cpp | 214 +++++++++++++-----
.../mismatch/mismatch_pred.pass.cpp | 119 ----------
12 files changed, 413 insertions(+), 189 deletions(-)
create mode 100644 libcxx/benchmarks/algorithms/mismatch.bench.cpp
create mode 100644 libcxx/include/__algorithm/simd_utils.h
delete mode 100644 libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp
diff --git a/libcxx/benchmarks/CMakeLists.txt b/libcxx/benchmarks/CMakeLists.txt
index 3dec6faea13a..387e013afeb6 100644
--- a/libcxx/benchmarks/CMakeLists.txt
+++ b/libcxx/benchmarks/CMakeLists.txt
@@ -183,6 +183,7 @@ set(BENCHMARK_TESTS
algorithms/make_heap_then_sort_heap.bench.cpp
algorithms/min.bench.cpp
algorithms/min_max_element.bench.cpp
+ algorithms/mismatch.bench.cpp
algorithms/pop_heap.bench.cpp
algorithms/pstl.stable_sort.bench.cpp
algorithms/push_heap.bench.cpp
diff --git a/libcxx/benchmarks/algorithms/mismatch.bench.cpp b/libcxx/benchmarks/algorithms/mismatch.bench.cpp
new file mode 100644
index 000000000000..9274932a764c
--- /dev/null
+++ b/libcxx/benchmarks/algorithms/mismatch.bench.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+#include
+
+// TODO: Look into benchmarking aligned and unaligned memory explicitly
+// (currently things happen to be aligned because they are malloced that way)
+template
+static void bm_mismatch(benchmark::State& state) {
+ std::vector vec1(state.range(), '1');
+ std::vector vec2(state.range(), '1');
+ std::mt19937_64 rng(std::random_device{}());
+
+ vec1.back() = '2';
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(vec1);
+ benchmark::DoNotOptimize(std::mismatch(vec1.begin(), vec1.end(), vec2.begin()));
+ }
+}
+BENCHMARK(bm_mismatch)->DenseRange(1, 8)->Range(16, 1 << 20);
+BENCHMARK(bm_mismatch)->DenseRange(1, 8)->Range(16, 1 << 20);
+BENCHMARK(bm_mismatch)->DenseRange(1, 8)->Range(16, 1 << 20);
+
+BENCHMARK_MAIN();
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index cac42f9c3c3f..dd39c1bbbc78 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -51,6 +51,8 @@ Improvements and New Features
- The performance of growing ``std::vector`` has been improved for trivially relocatable types.
- The performance of ``ranges::fill`` and ``ranges::fill_n`` has been improved for ``vector::iterator``\s,
resulting in a performance increase of up to 1400x.
+- The ``std::mismatch`` algorithm has been optimized for integral types, which can lead up to 40x performance
+ improvements.
Deprecations and Removals
-------------------------
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 6ed8d21d98a1..982b85e4e2d6 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -217,6 +217,7 @@ set(files
__algorithm/shift_right.h
__algorithm/shuffle.h
__algorithm/sift_down.h
+ __algorithm/simd_utils.h
__algorithm/sort.h
__algorithm/sort_heap.h
__algorithm/stable_partition.h
diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h
index d345b6048a7e..4eb693a1f2e9 100644
--- a/libcxx/include/__algorithm/mismatch.h
+++ b/libcxx/include/__algorithm/mismatch.h
@@ -11,23 +11,93 @@
#define _LIBCPP___ALGORITHM_MISMATCH_H
#include <__algorithm/comp.h>
+#include <__algorithm/simd_utils.h>
+#include <__algorithm/unwrap_iter.h>
#include <__config>
-#include <__iterator/iterator_traits.h>
+#include <__functional/identity.h>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_constant_evaluated.h>
+#include <__type_traits/is_equality_comparable.h>
+#include <__type_traits/operation_traits.h>
+#include <__utility/move.h>
#include <__utility/pair.h>
+#include <__utility/unreachable.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2>
+__mismatch_loop(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+ while (__first1 != __last1) {
+ if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
+ break;
+ ++__first1;
+ ++__first2;
+ }
+ return std::make_pair(std::move(__first1), std::move(__first2));
+}
+
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2>
+__mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+ return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2);
+}
+
+#if _LIBCPP_VECTORIZE_ALGORITHMS
+
+template ::value && __desugars_to<__equal_tag, _Pred, _Tp, _Tp>::value &&
+ __is_identity<_Proj1>::value && __is_identity<_Proj2>::value,
+ int> = 0>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*>
+__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+ constexpr size_t __unroll_count = 4;
+ constexpr size_t __vec_size = __native_vector_size<_Tp>;
+ using __vec = __simd_vector<_Tp, __vec_size>;
+ if (!__libcpp_is_constant_evaluated()) {
+ while (static_cast(__last1 - __first1) >= __unroll_count * __vec_size) [[__unlikely__]] {
+ __vec __lhs[__unroll_count];
+ __vec __rhs[__unroll_count];
+
+ for (size_t __i = 0; __i != __unroll_count; ++__i) {
+ __lhs[__i] = std::__load_vector<__vec>(__first1 + __i * __vec_size);
+ __rhs[__i] = std::__load_vector<__vec>(__first2 + __i * __vec_size);
+ }
+
+ for (size_t __i = 0; __i != __unroll_count; ++__i) {
+ if (auto __cmp_res = __lhs[__i] == __rhs[__i]; !std::__all_of(__cmp_res)) {
+ auto __offset = __i * __vec_size + std::__find_first_not_set(__cmp_res);
+ return {__first1 + __offset, __first2 + __offset};
+ }
+ }
+
+ __first1 += __unroll_count * __vec_size;
+ __first2 += __unroll_count * __vec_size;
+ }
+ }
+ // TODO: Consider vectorizing the tail
+ return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2);
+}
+
+#endif // _LIBCPP_VECTORIZE_ALGORITHMS
+
template
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) {
- for (; __first1 != __last1; ++__first1, (void)++__first2)
- if (!__pred(*__first1, *__first2))
- break;
- return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ __identity __proj;
+ auto __res = std::__mismatch(
+ std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred, __proj, __proj);
+ return std::make_pair(std::__rewrap_iter(__first1, __res.first), std::__rewrap_iter(__first2, __res.second));
}
template
@@ -59,4 +129,6 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_MISMATCH_H
diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h
new file mode 100644
index 000000000000..1aedb3db010f
--- /dev/null
+++ b/libcxx/include/__algorithm/simd_utils.h
@@ -0,0 +1,123 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_SIMD_UTILS_H
+#define _LIBCPP___ALGORITHM_SIMD_UTILS_H
+
+#include <__bit/bit_cast.h>
+#include <__bit/countr.h>
+#include <__config>
+#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/is_same.h>
+#include <__utility/integer_sequence.h>
+#include
+#include
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+// TODO: Find out how altivec changes things and allow vectorizations there too.
+#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1700 && !defined(__ALTIVEC__)
+# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1
+#else
+# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0
+#endif
+
+#if _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS && !defined(__OPTIMIZE_SIZE__)
+# define _LIBCPP_VECTORIZE_ALGORITHMS 1
+#else
+# define _LIBCPP_VECTORIZE_ALGORITHMS 0
+#endif
+
+#if _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// This isn't specialized for 64 byte vectors on purpose. They have the potential to significantly reduce performance
+// in mixed simd/non-simd workloads and don't provide any performance improvement for currently vectorized algorithms
+// as far as benchmarks are concerned.
+# if defined(__AVX__)
+template
+inline constexpr size_t __native_vector_size = 32 / sizeof(_Tp);
+# elif defined(__SSE__) || defined(__ARM_NEON__)
+template
+inline constexpr size_t __native_vector_size = 16 / sizeof(_Tp);
+# elif defined(__MMX__)
+template
+inline constexpr size_t __native_vector_size = 8 / sizeof(_Tp);
+# else
+template
+inline constexpr size_t __native_vector_size = 1;
+# endif
+
+template
+using __simd_vector __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT;
+
+template
+inline constexpr size_t __simd_vector_size_v = []() -> size_t {
+ static_assert(_False, "Not a vector!");
+}();
+
+template
+inline constexpr size_t __simd_vector_size_v<__simd_vector<_Tp, _Np>> = _Np;
+
+template
+_LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector<_Tp, _Np>) {
+ return _Tp{};
+}
+
+template
+using __simd_vector_underlying_type_t = decltype(std::__simd_vector_underlying_type_impl(_VecT{}));
+
+// This isn't inlined without always_inline when loading chars.
+template
+_LIBCPP_NODISCARD _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __load_vector(const _Tp* __ptr) noexcept {
+ return [=](index_sequence<_Indices...>) _LIBCPP_ALWAYS_INLINE noexcept {
+ return _VecT{__ptr[_Indices]...};
+ }(make_index_sequence<__simd_vector_size_v<_VecT>>{});
+}
+
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept {
+ return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector));
+}
+
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+ using __mask_vec = __simd_vector;
+
+ // This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876
+ auto __impl = [&](_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept {
+ return std::__countr_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec)));
+ };
+
+ if constexpr (sizeof(__mask_vec) == sizeof(uint8_t)) {
+ return __impl(uint8_t{});
+ } else if constexpr (sizeof(__mask_vec) == sizeof(uint16_t)) {
+ return __impl(uint16_t{});
+ } else if constexpr (sizeof(__mask_vec) == sizeof(uint32_t)) {
+ return __impl(uint32_t{});
+ } else if constexpr (sizeof(__mask_vec) == sizeof(uint64_t)) {
+ return __impl(uint64_t{});
+ } else {
+ static_assert(sizeof(__mask_vec) == 0, "unexpected required size for mask integer type");
+ return 0;
+ }
+}
+
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+ return std::__find_first_set(~__vec);
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS
+
+#endif // _LIBCPP___ALGORITHM_SIMD_UTILS_H
diff --git a/libcxx/include/__bit/bit_cast.h b/libcxx/include/__bit/bit_cast.h
index f20b39ae748b..6298810f3733 100644
--- a/libcxx/include/__bit/bit_cast.h
+++ b/libcxx/include/__bit/bit_cast.h
@@ -19,6 +19,15 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+#ifndef _LIBCPP_CXX03_LANG
+
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr _ToType __bit_cast(const _FromType& __from) noexcept {
+ return __builtin_bit_cast(_ToType, __from);
+}
+
+#endif // _LIBCPP_CXX03_LANG
+
#if _LIBCPP_STD_VER >= 20
template
diff --git a/libcxx/include/__bit/countr.h b/libcxx/include/__bit/countr.h
index 0cc679f87a99..b6b3ac52ca4e 100644
--- a/libcxx/include/__bit/countr.h
+++ b/libcxx/include/__bit/countr.h
@@ -35,10 +35,8 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ct
return __builtin_ctzll(__x);
}
-#if _LIBCPP_STD_VER >= 20
-
-template <__libcpp_unsigned_integer _Tp>
-_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept {
+template
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero(_Tp __t) _NOEXCEPT {
if (__t == 0)
return numeric_limits<_Tp>::digits;
@@ -59,6 +57,13 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) n
}
}
+#if _LIBCPP_STD_VER >= 20
+
+template <__libcpp_unsigned_integer _Tp>
+_LIBCPP_NODISCARD_EXT _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 {
return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits;
diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp
index 77b7befd44f5..56ea58262828 100644
--- a/libcxx/include/libcxx.imp
+++ b/libcxx/include/libcxx.imp
@@ -217,6 +217,7 @@
{ 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" ] },
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index f36a47cef009..03d18775631e 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -697,7 +697,10 @@ module std_private_algorithm_minmax [system
export *
}
module std_private_algorithm_minmax_element [system] { header "__algorithm/minmax_element.h" }
-module std_private_algorithm_mismatch [system] { header "__algorithm/mismatch.h" }
+module std_private_algorithm_mismatch [system] {
+ header "__algorithm/mismatch.h"
+ export std_private_algorithm_simd_utils
+}
module std_private_algorithm_move [system] { header "__algorithm/move.h" }
module std_private_algorithm_move_backward [system] { header "__algorithm/move_backward.h" }
module std_private_algorithm_next_permutation [system] { header "__algorithm/next_permutation.h" }
@@ -1048,6 +1051,7 @@ module std_private_algorithm_sort [system
header "__algorithm/sort.h"
export std_private_debug_utils_strict_weak_ordering_check
}
+module std_private_algorithm_simd_utils [system] { header "__algorithm/simd_utils.h" }
module std_private_algorithm_sort_heap [system] { header "__algorithm/sort_heap.h" }
module std_private_algorithm_stable_partition [system] { header "__algorithm/stable_partition.h" }
module std_private_algorithm_stable_sort [system] { header "__algorithm/stable_sort.h" }
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp
index cc588c095ccf..e7f3994d977d 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp
@@ -16,79 +16,173 @@
// template
// constexpr pair // constexpr after c++17
// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2); // C++14
+//
+// template Pred>
+// requires CopyConstructible
+// constexpr pair // constexpr after c++17
+// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Pred pred);
+//
+// template
+// constexpr pair // constexpr after c++17
+// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred); // C++14
+
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=50000000
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=100000000
#include
+#include
#include
+#include
#include "test_macros.h"
#include "test_iterators.h"
-
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
- int ia[] = {1, 3, 6, 7};
- int ib[] = {1, 3};
- int ic[] = {1, 3, 5, 7};
- typedef cpp17_input_iterator II;
- typedef bidirectional_iterator BI;
-
- auto p1 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic));
- if (p1.first != ia+2 || p1.second != ic+2)
- return false;
-
- auto p2 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic), std::end(ic));
- if (p2.first != ia+2 || p2.second != ic+2)
- return false;
-
- auto p3 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic));
- if (p3.first != ib+2 || p3.second != ic+2)
- return false;
-
- auto p4 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic), std::end(ic));
- if (p4.first != ib+2 || p4.second != ic+2)
- return false;
-
- auto p5 = std::mismatch(II(std::begin(ib)), II(std::end(ib)), II(std::begin(ic)));
- if (p5.first != II(ib+2) || p5.second != II(ic+2))
- return false;
- auto p6 = std::mismatch(BI(std::begin(ib)), BI(std::end(ib)), BI(std::begin(ic)), BI(std::end(ic)));
- if (p6.first != BI(ib+2) || p6.second != BI(ic+2))
- return false;
-
- return true;
- }
+#include "type_algorithms.h"
+
+template
+TEST_CONSTEXPR_CXX20 void check(Container1 lhs, Container2 rhs, size_t offset) {
+ if (lhs.size() == rhs.size()) {
+ assert(std::mismatch(Iter(lhs.data()), Iter(lhs.data() + lhs.size()), Iter(rhs.data())) ==
+ std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
+
+ assert(std::mismatch(Iter(lhs.data()),
+ Iter(lhs.data() + lhs.size()),
+ Iter(rhs.data()),
+ std::equal_to()) ==
+ std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
+ }
+
+#if TEST_STD_VER >= 14
+ assert(
+ std::mismatch(Iter(lhs.data()), Iter(lhs.data() + lhs.size()), Iter(rhs.data()), Iter(rhs.data() + rhs.size())) ==
+ std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
+
+ assert(std::mismatch(Iter(lhs.data()),
+ Iter(lhs.data() + lhs.size()),
+ Iter(rhs.data()),
+ Iter(rhs.data() + rhs.size()),
+ std::equal_to()) ==
+ std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset)));
#endif
+}
-int main(int, char**)
-{
- int ia[] = {0, 1, 2, 2, 0, 1, 2, 3};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- int ib[] = {0, 1, 2, 3, 0, 1, 2, 3};
- const unsigned sb = sizeof(ib)/sizeof(ib[0]); ((void)sb); // unused in C++11
-
- typedef cpp17_input_iterator II;
- typedef random_access_iterator RAI;
-
- assert(std::mismatch(II(ia), II(ia + sa), II(ib))
- == (std::pair(II(ia+3), II(ib+3))));
-
- assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib))
- == (std::pair(RAI(ia+3), RAI(ib+3))));
-
-#if TEST_STD_VER > 11 // We have the four iteration version
- assert(std::mismatch(II(ia), II(ia + sa), II(ib), II(ib+sb))
- == (std::pair(II(ia+3), II(ib+3))));
+struct NonTrivial {
+ int i_;
+
+ TEST_CONSTEXPR_CXX20 NonTrivial(int i) : i_(i) {}
+ TEST_CONSTEXPR_CXX20 NonTrivial(NonTrivial&& other) : i_(other.i_) { other.i_ = 0; }
+
+ TEST_CONSTEXPR_CXX20 friend bool operator==(const NonTrivial& lhs, const NonTrivial& rhs) { return lhs.i_ == rhs.i_; }
+};
+
+struct ModTwoComp {
+ TEST_CONSTEXPR_CXX20 bool operator()(int lhs, int rhs) { return lhs % 2 == rhs % 2; }
+};
+
+template
+TEST_CONSTEXPR_CXX20 bool test() {
+ { // empty ranges
+ std::array lhs = {};
+ std::array rhs = {};
+ check(lhs, rhs, 0);
+ }
+
+ { // same range without mismatch
+ std::array lhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ std::array rhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ check(lhs, rhs, 8);
+ }
+
+ { // same range with mismatch
+ std::array lhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ std::array rhs = {0, 1, 2, 3, 0, 1, 2, 3};
+ check(lhs, rhs, 3);
+ }
+
+ { // second range is smaller
+ std::array lhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ std::array rhs = {0, 1};
+ check(lhs, rhs, 2);
+ }
+
+ { // first range is smaller
+ std::array lhs = {0, 1};
+ std::array rhs = {0, 1, 2, 2, 0, 1, 2, 3};
+ check(lhs, rhs, 2);
+ }
+
+ { // use a custom comparator
+ std::array lhs = {0, 2, 3, 4};
+ std::array rhs = {0, 0, 4, 4};
+ assert(std::mismatch(lhs.data(), lhs.data() + lhs.size(), rhs.data(), ModTwoComp()) ==
+ std::make_pair(lhs.data() + 2, rhs.data() + 2));
+#if TEST_STD_VER >= 14
+ assert(std::mismatch(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size(), ModTwoComp()) ==
+ std::make_pair(lhs.data() + 2, rhs.data() + 2));
+#endif
+ }
- assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib), RAI(ib+sb))
- == (std::pair(RAI(ia+3), RAI(ib+3))));
+ return true;
+}
+struct Test {
+ template
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ test();
+ }
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ types::for_each(types::cpp17_input_iterator_list(), Test());
+
+ { // use a non-integer type to also test the general case - all elements match
+ std::array lhs = {1, 2, 3, 4, 5, 6, 7, 8};
+ std::array rhs = {1, 2, 3, 4, 5, 6, 7, 8};
+ check(std::move(lhs), std::move(rhs), 8);
+ }
+
+ { // use a non-integer type to also test the general case - not all elements match
+ std::array lhs = {1, 2, 3, 4, 7, 6, 7, 8};
+ std::array rhs = {1, 2, 3, 4, 5, 6, 7, 8};
+ check(std::move(lhs), std::move(rhs), 4);
+ }
+
+ return true;
+}
- assert(std::mismatch(II(ia), II(ia + sa), II(ib), II(ib+2))
- == (std::pair(II(ia+2), II(ib+2))));
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
#endif
-#if TEST_STD_VER > 17
- static_assert(test_constexpr());
-#endif
+ { // check with a lot of elements to test the vectorization optimization
+ {
+ std::vector lhs(256);
+ std::vector rhs(256);
+ for (size_t i = 0; i != lhs.size(); ++i) {
+ lhs[i] = 1;
+ check(lhs, rhs, i);
+ lhs[i] = 0;
+ rhs[i] = 1;
+ check(lhs, rhs, i);
+ rhs[i] = 0;
+ }
+ }
+
+ {
+ std::vector lhs(256);
+ std::vector rhs(256);
+ for (size_t i = 0; i != lhs.size(); ++i) {
+ lhs[i] = 1;
+ check(lhs, rhs, i);
+ lhs[i] = 0;
+ rhs[i] = 1;
+ check(lhs, rhs, i);
+ rhs[i] = 0;
+ }
+ }
+ }
return 0;
}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp
deleted file mode 100644
index bda4ec7ba5ed..000000000000
--- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-//
-
-// template Pred>
-// requires CopyConstructible
-// constexpr pair // constexpr after c++17
-// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Pred pred);
-//
-// template
-// constexpr pair // constexpr after c++17
-// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred); // C++14
-
-#include
-#include
-#include
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "counting_predicates.h"
-
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool eq(int a, int b) { return a == b; }
-
-TEST_CONSTEXPR bool test_constexpr() {
- int ia[] = {1, 3, 6, 7};
- int ib[] = {1, 3};
- int ic[] = {1, 3, 5, 7};
- typedef cpp17_input_iterator II;
- typedef bidirectional_iterator BI;
-
- auto p1 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic), eq);
- if (p1.first != ia+2 || p1.second != ic+2)
- return false;
-
- auto p2 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic), std::end(ic), eq);
- if (p2.first != ia+2 || p2.second != ic+2)
- return false;
-
- auto p3 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic), eq);
- if (p3.first != ib+2 || p3.second != ic+2)
- return false;
-
- auto p4 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic), std::end(ic), eq);
- if (p4.first != ib+2 || p4.second != ic+2)
- return false;
-
- auto p5 = std::mismatch(II(std::begin(ib)), II(std::end(ib)), II(std::begin(ic)), eq);
- if (p5.first != II(ib+2) || p5.second != II(ic+2))
- return false;
- auto p6 = std::mismatch(BI(std::begin(ib)), BI(std::end(ib)), BI(std::begin(ic)), BI(std::end(ic)), eq);
- if (p6.first != BI(ib+2) || p6.second != BI(ic+2))
- return false;
-
- return true;
- }
-#endif
-
-
-#if TEST_STD_VER > 11
-#define HAS_FOUR_ITERATOR_VERSION
-#endif
-
-int main(int, char**)
-{
- int ia[] = {0, 1, 2, 2, 0, 1, 2, 3};
- const unsigned sa = sizeof(ia)/sizeof(ia[0]);
- int ib[] = {0, 1, 2, 3, 0, 1, 2, 3};
- const unsigned sb = sizeof(ib)/sizeof(ib[0]); ((void)sb); // unused in C++11
-
- typedef cpp17_input_iterator II;
- typedef random_access_iterator RAI;
- typedef std::equal_to EQ;
-
- assert(std::mismatch(II(ia), II(ia + sa), II(ib), EQ())
- == (std::pair