(argv[0][0]));
}
diff --git a/clang/test/OpenMP/taskloop_codegen.cpp b/clang/test/OpenMP/taskloop_codegen.cpp
index 69f8d3b160bfd..d1197607a2684 100644
--- a/clang/test/OpenMP/taskloop_codegen.cpp
+++ b/clang/test/OpenMP/taskloop_codegen.cpp
@@ -5,7 +5,12 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fopenmp-version=60 -DOMP60 -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK6
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=60 -DOMP60 -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=60 -DOMP60 -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK6
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -241,4 +246,52 @@ void taskloop_with_class() {
}
}
+#ifdef OMP60
+void test_threadset()
+{
+#pragma omp taskloop threadset(omp_team)
+ for (int i = 0; i < 10; ++i) {
+ }
+#pragma omp taskloop threadset(omp_pool)
+ for (int i = 0; i < 10; ++i) {
+ }
+}
+#endif // OMP60
+// CHECK6-LABEL: define void @_Z14test_threadsetv()
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON_14:%.*]], align 1
+// CHECK6-NEXT: %[[TMP:.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[AGG_CAPTURED1:%.*]] = alloca [[STRUCT_ANON_16:%.*]], align 1
+// CHECK6-NEXT: %[[TMP2:.*]] = alloca i32, align 4
+// CHECK6-NEXT: %[[TID0:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB_PTR:[0-9]+]])
+// CHECK6-NEXT: call void @__kmpc_taskgroup(ptr @1, i32 %[[TID0:.*]])
+// CHECK6-NEXT: %[[TID1:.*]] = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %[[TID0:.*]], i32 1, i64 80, i64 1, ptr @.omp_task_entry..[[ENTRY1:[0-9]+]])
+// CHECK6-NEXT: %[[TID2:.*]] = getelementptr inbounds nuw %struct.kmp_task_t_with_privates{{.*}}, ptr %[[TID1:.*]], i32 0, i32 0
+// CHECK6-NEXT: %[[TID3:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID2:.*]], i32 0, i32 5
+// CHECK6-NEXT: store i64 0, ptr %[[TID3:.*]], align 8
+// CHECK6-NEXT: %[[TID4:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID2:.*]], i32 0, i32 6
+// CHECK6-NEXT: store i64 9, ptr %[[TID4:.*]], align 8
+// CHECK6-NEXT: %[[TID5:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID2:.*]], i32 0, i32 7
+// CHECK6-NEXT: store i64 1, ptr %[[TID5:.*]], align 8
+// CHECK6-NEXT: %[[TID6:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID2:.*]], i32 0, i32 9
+// CHECK6-NEXT: call void @llvm.memset.p0.i64(ptr align 8 %[[TID6:.*]], i8 0, i64 8, i1 false)
+// CHECK6-NEXT: %[[TID7:.*]] = load i64, ptr %[[TID5:.*]], align 8
+// CHECK6-NEXT: call void @__kmpc_taskloop(ptr @1, i32 %[[TID0:.*]], ptr %[[TID1:.*]], i32 1, ptr %[[TID3:.*]], ptr %4, i64 %[[TID7:.*]], i32 1, i32 0, i64 0, ptr null)
+// CHECK6-NEXT: call void @__kmpc_end_taskgroup(ptr @1, i32 %[[TID0:.*]])
+// CHECK6-NEXT: call void @__kmpc_taskgroup(ptr @1, i32 %[[TID0:.*]])
+// CHECK6-NEXT: %[[TID8:.*]] = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %[[TID0:.*]], i32 129, i64 80, i64 1, ptr @.omp_task_entry..[[ENTRY1:[0-9]+]])
+// CHECK6-NEXT: %[[TID9:.*]] = getelementptr inbounds nuw %struct.kmp_task_t_with_privates{{.*}}, ptr %[[TID8:.*]], i32 0, i32 0
+// CHECK6-NEXT: %[[TID10:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID9:.*]], i32 0, i32 5
+// CHECK6-NEXT: store i64 0, ptr %[[TID10:.*]], align 8
+// CHECK6-NEXT: %[[TID11:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID9:.*]], i32 0, i32 6
+// CHECK6-NEXT: store i64 9, ptr %[[TID11:.*]], align 8
+// CHECK6-NEXT: %[[TID12:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID9:.*]], i32 0, i32 7
+// CHECK6-NEXT: store i64 1, ptr %[[TID12:.*]], align 8
+// CHECK6-NEXT: %[[TID13:.*]] = getelementptr inbounds nuw %struct.kmp_task_t{{.*}}, ptr %[[TID9:.*]], i32 0, i32 9
+// CHECK6-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TID13:.*]], i8 0, i64 8, i1 false)
+// CHECK6-NEXT: %[[TID14:.*]] = load i64, ptr [[TID12:.*]], align 8
+// CHECK6-NEXT: call void @__kmpc_taskloop(ptr @1, i32 %[[TID0:.*]], ptr %[[TID8:.*]], i32 1, ptr %[[TID10:.*]], ptr %[[TID11:.*]], i64 %[[TID14:.*]], i32 1, i32 0, i64 0, ptr null)
+// CHECK6-NEXT: call void @__kmpc_end_taskgroup(ptr @1, i32 %[[TID0:.*]])
+// CHECK6-NEXT: ret void
+
#endif
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index fc27fd29da933..08776d9bcabfc 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2406,6 +2406,8 @@ void OMPClauseEnqueue::VisitOMPCompareClause(const OMPCompareClause *) {}
void OMPClauseEnqueue::VisitOMPFailClause(const OMPFailClause *) {}
+void OMPClauseEnqueue::VisitOMPThreadsetClause(const OMPThreadsetClause *) {}
+
void OMPClauseEnqueue::VisitOMPAbsentClause(const OMPAbsentClause *) {}
void OMPClauseEnqueue::VisitOMPHoldsClause(const OMPHoldsClause *) {}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index b7da22cf9fb22..ae9b28ee625cd 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -3113,11 +3113,11 @@ C++ defect report implementation status
Default initialization of POD classes? |
N/A |
-
+
| 511 |
- open |
+ NAD |
POD-structs with template assignment operators |
- Not resolved |
+ Unknown |
| 512 |
@@ -10895,7 +10895,7 @@ C++ defect report implementation status
| 1845 |
- drafting |
+ review |
Point of instantiation of a variable template specialization |
Not resolved |
@@ -12081,7 +12081,7 @@ C++ defect report implementation status
| 2042 |
- drafting |
+ review |
Exceptions and deallocation functions |
Not resolved |
@@ -12335,7 +12335,7 @@ C++ defect report implementation status
2084 |
CD4 |
NSDMIs and deleted union default constructors |
- Unknown |
+ Clang 3.1 |
| 2085 |
@@ -12837,7 +12837,7 @@ C++ defect report implementation status
| 2168 |
- open |
+ review |
Narrowing conversions and +/- infinity |
Not resolved |
@@ -14237,11 +14237,11 @@ C++ defect report implementation status
Constexpr virtual functions and temporary objects |
Unknown |
-
+
| 2401 |
- drafting |
+ C++20 |
Array decay vs prohibition of subobject non-type arguments |
- Not resolved |
+ Unknown |
| 2402 |
@@ -15171,7 +15171,7 @@ C++ defect report implementation status
| 2555 |
- drafting |
+ tentatively ready |
Ineffective redeclaration prevention for using-declarators |
Not resolved |
@@ -15311,23 +15311,23 @@ C++ defect report implementation status
Undefined behavior for preprocessing directives in macro arguments |
Not resolved |
-
+
| 2578 |
- open |
+ CD7 |
Undefined behavior when creating an invalid string literal via stringizing |
- Not resolved |
+ Unknown |
-
+
| 2579 |
- open |
+ CD7 |
Undefined behavior when token pasting does not create a preprocessing token |
- Not resolved |
+ Unknown |
-
+
| 2580 |
- open |
+ CD7 |
Undefined behavior with #line |
- Not resolved |
+ Unknown |
| 2581 |
@@ -17104,7 +17104,7 @@ C++ defect report implementation status
| 2875 |
- review |
+ tentatively ready |
Missing support for round-tripping null pointer values through indirection/address operators |
Not resolved |
@@ -17400,7 +17400,7 @@ C++ defect report implementation status
| 2923 |
- review |
+ tentatively ready |
Note about infinite loops and execution steps |
Not resolved |
@@ -17760,7 +17760,7 @@ C++ defect report implementation status
| 2983 |
- open |
+ review |
Non-type template parameters are not variables |
Not resolved |
@@ -17868,7 +17868,7 @@ C++ defect report implementation status
| 3001 |
- review |
+ tentatively ready |
Inconsistent restrictions for static_cast on pointers to out-of-lifetime objects |
Not resolved |
@@ -17932,7 +17932,7 @@ C++ defect report implementation status
| 3011 |
- open |
+ tentatively ready |
Parenthesized aggregate initialization for new-expressions |
Not resolved |
@@ -17992,7 +17992,7 @@ C++ defect report implementation status
| 3021 |
- open |
+ drafting |
Subsumption rules for fold expanded constraints |
Not resolved |
@@ -18058,7 +18058,7 @@ C++ defect report implementation status
| 3032 |
- open |
+ tentatively ready |
Template argument disambiguation |
Not resolved |
@@ -18184,7 +18184,7 @@ C++ defect report implementation status
| 3053 |
- open |
+ tentatively ready |
Allowing #undef likely |
Not resolved |
@@ -18265,6 +18265,210 @@ C++ defect report implementation status
tentatively ready |
Declarative nested-name-specifier in explicit instantiation |
Not resolved |
+
+
+ | 3067 |
+ open |
+ Array-to-pointer conversion with object type mismatch |
+ Not resolved |
+
+
+ | 3068 |
+ open |
+ Access checking in friends involving qualified-ids |
+ Not resolved |
+
+
+ | 3069 |
+ open |
+ Reference to wrong placeholder |
+ Not resolved |
+
+
+ | 3070 |
+ open |
+ Trivial assignment can skip member subobjects |
+ Not resolved |
+
+
+ | 3071 |
+ open |
+ Negative tuple_size in structured bindings |
+ Not resolved |
+
+
+ | 3072 |
+ open |
+ Incorrect examples for lambda SFINAE |
+ Not resolved |
+
+
+ | 3073 |
+ open |
+ Dependence of R on T2 is unclear |
+ Not resolved |
+
+
+ | 3074 |
+ tentatively ready |
+ Redundant ill-formedness for module macros |
+ Not resolved |
+
+
+ | 3075 |
+ tentatively ready |
+ Unclear matching of import directive |
+ Not resolved |
+
+
+ | 3076 |
+ tentatively ready |
+ Remove unnecessary IFNDR for malformed header-name-tokens |
+ Not resolved |
+
+
+ | 3077 |
+ tentatively ready |
+ Undesirable formation of import directive with string-literal |
+ Not resolved |
+
+
+ | 3078 |
+ review |
+ Different treatment of #include pp-tokens and header-name-tokens |
+ Not resolved |
+
+
+ | 3079 |
+ open |
+ Allow empty-declarations in anonymous unions |
+ Not resolved |
+
+
+ | 3080 |
+ tentatively ready |
+ Clarify kinds of permitted template template arguments |
+ Not resolved |
+
+
+ | 3081 |
+ review |
+ Require glvalue when splicing direct base class relationship |
+ Not resolved |
+
+
+ | 3082 |
+ tentatively ready |
+ Allow for call-compatible function types in reinterpret_cast |
+ Not resolved |
+
+
+ | 3083 |
+ tentatively ready |
+ Remove redundant restrictions on class and enum definitions |
+ Not resolved |
+
+
+ | 3084 |
+ tentatively ready |
+ compound-statements inside iteration-statements |
+ Not resolved |
+
+
+ | 3085 |
+ tentatively ready |
+ Apply restriction inside for-range-declaration |
+ Not resolved |
+
+
+ | 3086 |
+ tentatively ready |
+ Destringizing should consider all sorts of encoding-prefixes |
+ Not resolved |
+
+
+ | 3087 |
+ open |
+ Destringizing for raw string literals |
+ Not resolved |
+
+
+ | 3088 |
+ open |
+ Clarify macro treatment of identifiers with special meaning |
+ Not resolved |
+
+
+ | 3089 |
+ tentatively ready |
+ const-default-constructible improperly handles std::meta::info |
+ Not resolved |
+
+
+ | 3090 |
+ tentatively ready |
+ Internal linkage from header units |
+ Not resolved |
+
+
+ | 3091 |
+ review |
+ Linking of translation units as sequences of tokens |
+ Not resolved |
+
+
+ | 3092 |
+ tentatively ready |
+ base-specifiers are not "declared" |
+ Not resolved |
+
+
+ | 3093 |
+ open |
+ Missing integration of direct base class relationships |
+ Not resolved |
+
+
+ | 3094 |
+ review |
+ Rework phases for string literal concatenation and token formation |
+ Not resolved |
+
+
+ | 3095 |
+ open |
+ Type-dependent packs that are not structured binding packs |
+ Not resolved |
+
+
+ | 3096 |
+ open |
+ Value-dependence of size of structured binding pack with non-dependent initializer |
+ Not resolved |
+
+
+ | 3097 |
+ tentatively ready |
+ Lambda expression introduces a scope |
+ Not resolved |
+
+
+ | 3098 |
+ tentatively ready |
+ Remove redundancy "names or designates" |
+ Not resolved |
+
+
+ | 3099 |
+ open |
+ Instantiation of type aliases from alias templates is unspecified |
+ Not resolved |
+
+
+ | 3100 |
+ open |
+ Destruction order for objects with static storage duration |
+ Not resolved |
diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h
index 74924661d9a03..688d01704370d 100644
--- a/flang/include/flang/Lower/OpenMP/Clauses.h
+++ b/flang/include/flang/Lower/OpenMP/Clauses.h
@@ -294,6 +294,7 @@ using Permutation = tomp::clause::PermutationT;
using TaskReduction = tomp::clause::TaskReductionT;
using ThreadLimit = tomp::clause::ThreadLimitT;
using Threads = tomp::clause::ThreadsT;
+using Threadset = tomp::clause::ThreadsetT;
using Transparent = tomp::clause::TransparentT;
using To = tomp::clause::ToT;
using UnifiedAddress = tomp::clause::UnifiedAddressT;
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index bb970691c85c9..a7398a4ef970f 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -685,6 +685,8 @@ class ParseTreeDumper {
NODE_ENUM(OmpTaskDependenceType, Value)
NODE(parser, OmpTaskReductionClause)
NODE(OmpTaskReductionClause, Modifier)
+ NODE(parser, OmpThreadsetClause)
+ NODE_ENUM(OmpThreadsetClause, ThreadsetPolicy)
NODE(parser, OmpToClause)
NODE(OmpToClause, Modifier)
NODE(parser, OmpTraitProperty)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index c3a8c2eab15f2..375790af90b74 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4825,6 +4825,14 @@ struct OmpTaskReductionClause {
std::tuple t;
};
+// Ref: [6.0:442]
+// threadset-clause ->
+// THREADSET(omp_pool|omp_team)
+struct OmpThreadsetClause {
+ ENUM_CLASS(ThreadsetPolicy, Omp_Pool, Omp_Team)
+ WRAPPER_CLASS_BOILERPLATE(OmpThreadsetClause, ThreadsetPolicy);
+};
+
// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
//
// to-clause (in DECLARE TARGET) ->
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index d39f9dda92a28..0f60b47991004 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1482,6 +1482,21 @@ ThreadLimit make(const parser::OmpClause::ThreadLimit &inp,
return ThreadLimit{/*Threadlim=*/makeExpr(inp.v, semaCtx)};
}
+Threadset make(const parser::OmpClause::Threadset &inp,
+ semantics::SemanticsContext &semaCtx) {
+ // inp.v -> parser::OmpThreadsetClause
+ using wrapped = parser::OmpThreadsetClause;
+
+ CLAUSET_ENUM_CONVERT( //
+ convert, wrapped::ThreadsetPolicy, Threadset::ThreadsetPolicy,
+ // clang-format off
+ MS(Omp_Pool, Omp_Pool)
+ MS(Omp_Team, Omp_Team)
+ // clang-format on
+ );
+ return Threadset{/*ThreadsetPolicy=*/convert(inp.v.v)};
+}
+
// Threadprivate: empty
// Threads: empty
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index ec69e014fe0e7..e0b78eda68909 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3406,6 +3406,7 @@ CHECK_SIMPLE_CLAUSE(Read, OMPC_read)
CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate)
CHECK_SIMPLE_CLAUSE(Groupprivate, OMPC_groupprivate)
CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads)
+CHECK_SIMPLE_CLAUSE(Threadset, OMPC_threadset)
CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch)
CHECK_SIMPLE_CLAUSE(Link, OMPC_link)
CHECK_SIMPLE_CLAUSE(Indirect, OMPC_indirect)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index b4c081dcdff1b..357f77b7d27d6 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1050,8 +1050,7 @@ typedef __char32_t char32_t;
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
# endif
-// TODO(LLVM 22): Remove the workaround
-# if defined(__OBJC__) && (!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER < 2001)
+# if defined(__OBJC__) && defined(_LIBCPP_APPLE_CLANG_VER)
# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS
# endif
@@ -1255,14 +1254,6 @@ typedef __char32_t char32_t;
# define _LIBCPP_DIAGNOSE_NULLPTR
# endif
-// TODO(LLVM 22): Remove this macro once LLVM19 support ends. __cpp_explicit_this_parameter has been set in LLVM20.
-// Clang-18 has support for deducing this, but it does not set the FTM.
-# if defined(__cpp_explicit_this_parameter) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1800)
-# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 1
-# else
-# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 0
-# endif
-
#endif // __cplusplus
#endif // _LIBCPP___CONFIG
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index c9936df30ff7f..38b85c6ac70de 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -61,14 +61,6 @@
// According to the Standard, `bitset::operator[] const` returns bool
# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
-// In LLVM 20, we've changed to take these ABI breaks unconditionally. These flags only exist in case someone is running
-// into the static_asserts we added to catch the ABI break and don't care that it is one.
-// TODO(LLVM 22): Remove these flags
-# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
-# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
-# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
-# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
-
// These flags are documented in ABIGuarantees.rst
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h
index ed5e76275ea87..19794f0f084ce 100644
--- a/libcxx/include/__format/format_arg.h
+++ b/libcxx/include/__format/format_arg.h
@@ -149,7 +149,7 @@ _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_
__libcpp_unreachable();
}
-# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# if _LIBCPP_STD_VER >= 26
template
_LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
@@ -200,7 +200,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<
__libcpp_unreachable();
}
-# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# endif // _LIBCPP_STD_VER >= 26
/// Contains the values used in basic_format_arg.
///
@@ -285,7 +285,7 @@ class _LIBCPP_NO_SPECIALIZATIONS basic_format_arg {
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; }
-# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# if _LIBCPP_STD_VER >= 26
// This function is user facing, so it must wrap the non-standard types of
// the "variant" in a handle to stay conforming. See __arg_t for more details.
@@ -329,7 +329,7 @@ class _LIBCPP_NO_SPECIALIZATIONS basic_format_arg {
}
}
-# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# endif // _LIBCPP_STD_VER >= 26
private:
using char_type = typename _Context::char_type;
@@ -371,11 +371,8 @@ class basic_format_arg<_Context>::handle {
// This function is user facing, so it must wrap the non-standard types of
// the "variant" in a handle to stay conforming. See __arg_t for more details.
template
-# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
-_LIBCPP_DEPRECATED_IN_CXX26
-# endif
- _LIBCPP_HIDE_FROM_ABI decltype(auto)
- visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
+_LIBCPP_DEPRECATED_IN_CXX26 _LIBCPP_HIDE_FROM_ABI decltype(auto)
+visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
switch (__arg.__type_) {
# if _LIBCPP_HAS_INT128
case __format::__arg_t::__i128: {
@@ -387,7 +384,7 @@ _LIBCPP_DEPRECATED_IN_CXX26
typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_};
return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h});
}
-# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# endif // _LIBCPP_HAS_INT128
default:
return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg);
}
diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h
index e672ee7ad0581..1771dd34b82fb 100644
--- a/libcxx/include/__format/format_context.h
+++ b/libcxx/include/__format/format_context.h
@@ -175,13 +175,13 @@ class basic_format_context::__itera
__format::__determine_arg_t(),
__basic_format_arg_value(__arg)};
};
-# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# if _LIBCPP_STD_VER >= 26
return static_cast<_Context*>(__c)->arg(__id).visit(std::move(__visitor));
# else
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
return std::visit_format_arg(std::move(__visitor), static_cast<_Context*>(__c)->arg(__id));
_LIBCPP_SUPPRESS_DEPRECATED_POP
-# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# endif // _LIBCPP_STD_VER >= 26
}) {
}
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 5432abb4ab39d..e1897949a47e6 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -83,18 +83,6 @@ struct __hash_node_base {
typedef _NodePtr __node_pointer;
typedef __node_base_pointer __next_pointer;
-// TODO(LLVM 22): Remove this check
-#ifndef _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
- static_assert(sizeof(__node_base_pointer) == sizeof(__node_pointer) && _LIBCPP_ALIGNOF(__node_base_pointer) ==
- _LIBCPP_ALIGNOF(__node_pointer),
- "It looks like you are using std::__hash_table (an implementation detail for the unordered containers) "
- "with a fancy pointer type that thas a different representation depending on whether it points to a "
- "__hash_table base pointer or a __hash_table node pointer (both of which are implementation details of "
- "the standard library). This means that your ABI is being broken between LLVM 19 and LLVM 20. If you "
- "don't care about your ABI being broken, define the _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB macro to "
- "silence this diagnostic.");
-#endif
-
__next_pointer __next_;
_LIBCPP_HIDE_FROM_ABI __next_pointer __ptr() _NOEXCEPT {
diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index f38688734b38a..3b43920443636 100644
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -117,15 +117,12 @@ template
concept __signed_integer_like = signed_integral<_Tp>;
template
-concept weakly_incrementable =
- // TODO: remove this once the clang bug is fixed (https://llvm.org/PR48173).
- !same_as<_Ip, bool> && // Currently, clang does not handle bool correctly.
- movable<_Ip> && requires(_Ip __i) {
- typename iter_difference_t<_Ip>;
- requires __signed_integer_like>;
- { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving
- __i++; // not required to be equality-preserving
- };
+concept weakly_incrementable = movable<_Ip> && requires(_Ip __i) {
+ typename iter_difference_t<_Ip>;
+ requires __signed_integer_like>;
+ { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving
+ __i++; // not required to be equality-preserving
+};
// [iterator.concept.inc]
template
diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 00db2a8289fb3..ff22cee7305d7 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -25,33 +25,26 @@ namespace __math {
// signbit
-// TODO(LLVM 22): Remove conditional once support for Clang 19 is dropped.
-#if defined(_LIBCPP_COMPILER_GCC) || __has_constexpr_builtin(__builtin_signbit)
-# define _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_CONSTEXPR_SINCE_CXX23
-#else
-# define _LIBCPP_SIGNBIT_CONSTEXPR
-#endif
-
// The universal C runtime (UCRT) in the WinSDK provides floating point overloads
// for std::signbit(). By defining our overloads as templates, we can work around
// this issue as templates are less preferred than non-template functions.
template
-[[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT {
return __builtin_signbit(__x);
}
template
-[[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT {
return __builtin_signbit(__x);
}
template
-[[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT {
return __builtin_signbit(__x);
}
template ::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {
return __x < 0;
}
diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
index ae85dfa452d72..ab1adf9cdbe68 100644
--- a/libcxx/include/__ranges/transform_view.h
+++ b/libcxx/include/__ranges/transform_view.h
@@ -13,7 +13,6 @@
#include <__compare/three_way_comparable.h>
#include <__concepts/constructible.h>
#include <__concepts/convertible_to.h>
-#include <__concepts/copyable.h>
#include <__concepts/derived_from.h>
#include <__concepts/equality_comparable.h>
#include <__concepts/invocable.h>
@@ -64,7 +63,7 @@ concept __regular_invocable_with_range_ref = regular_invocable<_Fn, range_refere
template
concept __transform_view_constraints =
view<_View> && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_View>> &&
- __is_referenceable_v>>;
+ __referenceable>>;
# if _LIBCPP_STD_VER >= 23
template
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 0738c8c6a5e2b..694796922c914 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -823,18 +823,6 @@ public:
using __node_allocator _LIBCPP_NODEBUG = __rebind_alloc<__alloc_traits, __node>;
using __node_traits _LIBCPP_NODEBUG = allocator_traits<__node_allocator>;
-// TODO(LLVM 22): Remove this check
-#ifndef _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
- static_assert(sizeof(__node_base_pointer) == sizeof(__end_node_pointer) && _LIBCPP_ALIGNOF(__node_base_pointer) ==
- _LIBCPP_ALIGNOF(__end_node_pointer),
- "It looks like you are using std::__tree (an implementation detail for (multi)map/set) with a fancy "
- "pointer type that thas a different representation depending on whether it points to a __tree base "
- "pointer or a __tree node pointer (both of which are implementation details of the standard library). "
- "This means that your ABI is being broken between LLVM 19 and LLVM 20. If you don't care about your "
- "ABI being broken, define the _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB macro to silence this "
- "diagnostic.");
-#endif
-
private:
// check for sane allocator pointer rebinding semantics. Rebinding the
// allocator for a new pointer type should be exactly the same as rebinding
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index 2ff549b4e15ce..3d097ce90cb09 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -30,14 +30,8 @@ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_tempo
#endif
-#if __has_builtin(__reference_constructs_from_temporary)
template
inline const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
-#else
-// TODO(LLVM 22): Remove this as all supported compilers should have __reference_constructs_from_temporary implemented.
-template
-inline const bool __reference_constructs_from_temporary_v = __reference_binds_to_temporary(_Tp, _Up);
-#endif
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index df7da20cfb611..88d863f494e86 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -284,17 +284,6 @@ struct __forward_node_traits {
typedef _NodePtr __node_pointer;
typedef __forward_begin_node<_NodePtr> __begin_node;
typedef __rebind_pointer_t<_NodePtr, __begin_node> __begin_node_pointer;
-
-// TODO(LLVM 22): Remove this check
-# ifndef _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
- static_assert(sizeof(__begin_node_pointer) == sizeof(__node_pointer) && _LIBCPP_ALIGNOF(__begin_node_pointer) ==
- _LIBCPP_ALIGNOF(__node_pointer),
- "It looks like you are using std::forward_list with a fancy pointer type that thas a different "
- "representation depending on whether it points to a forward_list base pointer or a forward_list node "
- "pointer (both of which are implementation details of the standard library). This means that your ABI "
- "is being broken between LLVM 19 and LLVM 20. If you don't care about your ABI being broken, define "
- "the _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB macro to silence this diagnostic.");
-# endif
};
template
diff --git a/libcxx/include/list b/libcxx/include/list
index c5c2a8508999c..0ff85d2ebcb86 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -276,17 +276,6 @@ template
struct __list_node_pointer_traits {
typedef __rebind_pointer_t<_VoidPtr, __list_node<_Tp, _VoidPtr> > __node_pointer;
typedef __rebind_pointer_t<_VoidPtr, __list_node_base<_Tp, _VoidPtr> > __base_pointer;
-
-// TODO(LLVM 22): Remove this check
-# ifndef _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
- static_assert(sizeof(__node_pointer) == sizeof(__node_pointer) && _LIBCPP_ALIGNOF(__base_pointer) ==
- _LIBCPP_ALIGNOF(__node_pointer),
- "It looks like you are using std::list with a fancy pointer type that thas a different representation "
- "depending on whether it points to a list base pointer or a list node pointer (both of which are "
- "implementation details of the standard library). This means that your ABI is being broken between "
- "LLVM 19 and LLVM 20. If you don't care about your ABI being broken, define the "
- "_LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB macro to silence this diagnostic.");
-# endif
};
template
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 5f3bb72e0678b..466f501b5f4f8 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -301,7 +301,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool __tuple_compare_equal(c
template >>
inline constexpr bool __can_tuple_compare_equal = false;
-// TODO(LLVM 22): Remove `tuple_size_v<_Tp> == tuple_size_v<_Up>` here once once LLVM-20 support ends
+// TODO(LLVM 23): Remove `tuple_size_v<_Tp> == tuple_size_v<_Up>` here once once LLVM-20 support ends
// because the resolution of CWG2369 landed in LLVM-21.
template
requires(tuple_size_v<_Tp> == tuple_size_v<_Up>)
@@ -328,7 +328,7 @@ concept __tuple_like_no_tuple = __tuple_like<_Tp> && !__is_tuple_v<_Tp>;
template
struct __tuple_common_comparison_category_impl {};
-// TODO(LLVM 22): Remove `tuple_size_v<_Tp> == tuple_size_v<_Up>` here once once LLVM-20 support ends
+// TODO(LLVM 23): Remove `tuple_size_v<_Tp> == tuple_size_v<_Up>` here once once LLVM-20 support ends
// because the resolution of CWG2369 landed in LLVM-21.
template
requires(tuple_size_v<_Tp> == tuple_size_v<_Up>) && requires {
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 9beef146f203c..8e958581a6b07 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -1299,7 +1299,7 @@ public:
__impl_.__swap(__that.__impl_);
}
-# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
+# if _LIBCPP_STD_VER >= 26
// Helper class to implement [variant.visit]/10
// Constraints: The call to visit does not use an explicit template-argument-list
// that begins with a type template-argument.
diff --git a/libcxx/test/libcxx-03/utilities/meta/is_referenceable.compile.pass.cpp b/libcxx/test/libcxx-03/utilities/meta/is_referenceable.compile.pass.cpp
index 093bbae289723..f39d1a5da41af 100644
--- a/libcxx/test/libcxx-03/utilities/meta/is_referenceable.compile.pass.cpp
+++ b/libcxx/test/libcxx-03/utilities/meta/is_referenceable.compile.pass.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
//
-// __is_referenceable_v
+// __libcpp_is_referenceable
//
// [defns.referenceable] defines "a referenceable type" as:
// An object type, a function type that does not have cv-qualifiers
diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
index 3f17f21e8c108..20887b8cf2678 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp
@@ -220,16 +220,9 @@ int main(int, char**) {
ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
-// TODO(LLVM 22): Remove `__has_constexpr_builtin` conditional once support for Clang 19 is dropped.
-#if !__has_constexpr_builtin(__builtin_signbit)
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
- ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
-#else
ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);
ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1);
-#endif
ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0);
ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0);
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
index 09ebd0069b3a9..3e9bdd98cd394 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
@@ -8,15 +8,6 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-// With clang-cl, some warnings have a 'which is a Microsoft extension' suffix
-// which break the tests. But #102851 will turn it into an error, making the test pass.
-// However, upstream libcxx buildbots do not build clang from source while testing, so
-// this tests still expected to fail on these bots.
-//
-// TODO(LLVM 22): Remove '0-1' from 'expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}}'
-// and remove 'expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}}'
-// once LLVM 22 releases. See https://llvm.org/PR104885.
-
// Test the mandates
// template constexpr auto transform_error(F&& f) &;
@@ -55,41 +46,39 @@ void test() {
{
std::expected e;
e.transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
// expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected for {{.*}} is ill-formed.}}
- // expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}}
+ // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
e.transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
// expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected for {{.*}} is ill-formed.}}
- // expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}}
}
// Test const& overload
{
const std::expected e;
e.transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
e.transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
}
// Test && overload
{
std::expected e;
std::move(e).transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
std::move(e).transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
}
// Test const&& overload
{
const std::expected e;
std::move(e).transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
std::move(e).transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
}
}
// clang-format on
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
index 9fd7452af64fb..c5acc27af03ea 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
@@ -8,16 +8,6 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-// With clang-cl, some warnings have a 'which is a Microsoft extension' suffix
-// which break the tests. But #102851 will turn it into an error, making the test pass.
-// However, upstream libcxx buildbots do not build clang from source while testing, so
-// this tests still expected to fail on these bots.
-//
-// TODO(LLVM 22): Remove '0-1' from 'expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}}'
-// and remove 'expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}}'
-// and remove 'expected-error-re@*:* 0-1 {{call to deleted constructor of {{.*}}}}'
-// once LLVM 22 releases. See See https://llvm.org/PR104885.
-
// Test the mandates
// template constexpr auto transform_error(F&& f) &;
@@ -56,43 +46,36 @@ void test() {
{
std::expected e;
e.transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
// expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected with a E that is not a valid argument for unexpected is ill-formed}}
- // expected-error-re@*:* 0-1 {{call to deleted constructor of {{.*}}}}
- // expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}}
+ // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
e.transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
// expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected with a E that is not a valid argument for unexpected is ill-formed}}
- // expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}}
}
// Test const& overload
{
const std::expected e;
e.transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
e.transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
- // expected-error-re@*:* 0-1 {{call to deleted constructor of {{.*}}}}
+ // expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
}
// Test && overload
{
std::expected e;
std::move(e).transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
std::move(e).transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
}
// Test const&& overload
{
const std::expected e;
std::move(e).transform_error(return_unexpected); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
std::move(e).transform_error(return_no_object); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
- // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}}
}
}
// clang-format on
diff --git a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp
index 20e0a5ed66bd0..68fe8b6de41d6 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.pass.cpp
@@ -8,8 +8,6 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
-// The tested functionality needs deducing this.
-// XFAIL: apple-clang
//
diff --git a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp
index 8a79dd4d50f20..4ae63e896caed 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit.return_type.pass.cpp
@@ -8,8 +8,6 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
-// The tested functionality needs deducing this.
-// XFAIL: apple-clang
//
diff --git a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.deprecated.verify.cpp b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.deprecated.verify.cpp
index 146ceba58872e..77df72d3c4c6c 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.deprecated.verify.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.deprecated.verify.cpp
@@ -8,7 +8,6 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
-// XFAIL: apple-clang
//
diff --git a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp
index d99675a71f321..9b7c8a7f4f8b4 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp
@@ -9,6 +9,8 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+
//
// template
@@ -25,10 +27,6 @@
#include "make_string.h"
#include "min_allocator.h"
-#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
-TEST_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations")
-#endif
-
template
void test(From value) {
auto store = std::make_format_args(value);
diff --git a/libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp b/libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp
index c7dd82d726b3a..cbddc4f437a53 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp
@@ -32,7 +32,7 @@ void test(From value) {
else
assert(false);
};
-#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
+#if TEST_STD_VER >= 26
format_args.get(0).visit(visitor);
#else
std::visit_format_arg(visitor, format_args.get(0));
@@ -47,7 +47,7 @@ void test_handle(T value) {
std::basic_format_args format_args{store};
auto visitor = [](auto a) { assert((std::is_same_v::handle>)); };
-#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
+#if TEST_STD_VER >= 26
format_args.get(0).visit(visitor);
#else
std::visit_format_arg(visitor, format_args.get(0));
@@ -73,7 +73,7 @@ void test_string_view(From value) {
else
assert(false);
};
-#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
+#if TEST_STD_VER >= 26
format_args.get(0).visit(visitor);
#else
std::visit_format_arg(visitor, format_args.get(0));
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp
index d78de0eec8e53..0f6a6734264c3 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp
@@ -16,17 +16,6 @@
#include
#include
#include
-#include "test_macros.h"
-
-#if TEST_HAS_BUILTIN(__reference_constructs_from_temporary)
-# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_constructs_from_temporary(__VA_ARGS__), "")
-# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) \
- static_assert(!__reference_constructs_from_temporary(__VA_ARGS__), "")
-#else
-// TODO(LLVM 22): Remove this as all support compilers should have __reference_constructs_from_temporary implemented.
-# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "")
-# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "")
-#endif
template
struct ConvertsTo {
@@ -42,17 +31,6 @@ struct ConvertsTo {
struct Base {};
struct Derived : Base {};
-
-static_assert(std::is_same::value, "");
-ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype("abc"));
-ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype(("abc")));
-ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, const char*&&);
-
-ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(int&, const ConvertsTo&);
-ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(const int&, ConvertsTo&);
-ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(Base&, Derived&);
-
-
static_assert(std::is_constructible>::value, "");
static_assert(std::is_constructible>::value, "");
diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/robust_against_adl.pass.cpp
index 7be7c7ff9122b..38cf34a9c699c 100644
--- a/libcxx/test/std/utilities/variant/variant.visit.member/robust_against_adl.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.visit.member/robust_against_adl.pass.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// XFAIL: apple-clang
//
diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp
index f68112d30fc35..aeb1297c136ae 100644
--- a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp
@@ -7,8 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// The tested functionality needs deducing this.
-// XFAIL: apple-clang
//
diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp
index 90320ae518c34..7ca05908ab340 100644
--- a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp
@@ -7,8 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// The tested functionality needs deducing this.
-// XFAIL: apple-clang
//
diff --git a/libcxx/test/support/test_basic_format_arg.h b/libcxx/test/support/test_basic_format_arg.h
index f51f6e97cbed0..99cd558c3c5bf 100644
--- a/libcxx/test/support/test_basic_format_arg.h
+++ b/libcxx/test/support/test_basic_format_arg.h
@@ -21,7 +21,7 @@ bool test_basic_format_arg(std::basic_format_arg arg, T expected) {
else
return false;
};
-#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
+#if TEST_STD_VER >= 26
return arg.visit(std::move(visitor));
#else
return std::visit_format_arg(std::move(visitor), arg);
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index c4e1600572456..8d88d6fad7d0b 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -531,13 +531,6 @@ inline Tp const& DoNotOptimize(Tp const& value) {
# define TEST_IF_AIX(arg_true, arg_false) arg_false
#endif
-// Clang-18 has support for deducing this, but it does not set the FTM.
-#ifdef _LIBCPP_USE_FROZEN_CXX03_HEADERS
-// This is a C++20 featue, so we don't care whether the compiler could support it
-#elif defined(_LIBCPP_VERSION) && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
-# define TEST_HAS_EXPLICIT_THIS_PARAMETER
-#endif
-
// Placement `operator new`/`operator new[]` are not yet constexpr in C++26
// when using MS ABI, because they are from .
#if defined(__cpp_lib_constexpr_new) && __cpp_lib_constexpr_new >= 202406L
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 8f3652172dfdf..d892c01f0bc71 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -10,8 +10,8 @@
import subprocess
import signal
import sys
+import threading
import warnings
-import selectors
import time
from typing import (
Any,
@@ -139,6 +139,35 @@ def dump_memory(base_addr, data, num_per_line, outfile):
outfile.write("\n")
+def read_packet(
+ f: IO[bytes], trace_file: Optional[IO[str]] = None
+) -> Optional[ProtocolMessage]:
+ """Decode a JSON packet that starts with the content length and is
+ followed by the JSON bytes from a file 'f'. Returns None on EOF.
+ """
+ line = f.readline().decode("utf-8")
+ if len(line) == 0:
+ return None # EOF.
+
+ # Watch for line that starts with the prefix
+ prefix = "Content-Length: "
+ if line.startswith(prefix):
+ # Decode length of JSON bytes
+ length = int(line[len(prefix) :])
+ # Skip empty line
+ separator = f.readline().decode()
+ if separator != "":
+ Exception("malformed DAP content header, unexpected line: " + separator)
+ # Read JSON bytes
+ json_str = f.read(length).decode()
+ if trace_file:
+ trace_file.write("from adapter:\n%s\n" % (json_str))
+ # Decode the JSON bytes into a python dictionary
+ return json.loads(json_str)
+
+ raise Exception("unexpected malformed message from lldb-dap: " + line)
+
+
def packet_type_is(packet, packet_type):
return "type" in packet and packet["type"] == packet_type
@@ -170,8 +199,16 @@ def __init__(
self.log_file = log_file
self.send = send
self.recv = recv
- self.selector = selectors.DefaultSelector()
- self.selector.register(recv, selectors.EVENT_READ)
+
+ # Packets that have been received and processed but have not yet been
+ # requested by a test case.
+ self._pending_packets: List[Optional[ProtocolMessage]] = []
+ # Received packets that have not yet been processed.
+ self._recv_packets: List[Optional[ProtocolMessage]] = []
+ # Used as a mutex for _recv_packets and for notify when _recv_packets
+ # changes.
+ self._recv_condition = threading.Condition()
+ self._recv_thread = threading.Thread(target=self._read_packet_thread)
# session state
self.init_commands = init_commands
@@ -197,6 +234,9 @@ def __init__(
# keyed by breakpoint id
self.resolved_breakpoints: dict[str, Breakpoint] = {}
+ # trigger enqueue thread
+ self._recv_thread.start()
+
@classmethod
def encode_content(cls, s: str) -> bytes:
return ("Content-Length: %u\r\n\r\n%s" % (len(s), s)).encode("utf-8")
@@ -212,46 +252,17 @@ def validate_response(cls, command, response):
f"seq mismatch in response {command['seq']} != {response['request_seq']}"
)
- def _read_packet(
- self,
- timeout: float = DEFAULT_TIMEOUT,
- ) -> Optional[ProtocolMessage]:
- """Decode a JSON packet that starts with the content length and is
- followed by the JSON bytes from self.recv. Returns None on EOF.
- """
-
- ready = self.selector.select(timeout)
- if not ready:
- warnings.warn(
- "timeout occurred waiting for a packet, check if the test has a"
- " negative assertion and see if it can be inverted.",
- stacklevel=4,
- )
- return None # timeout
-
- line = self.recv.readline().decode("utf-8")
- if len(line) == 0:
- return None # EOF.
-
- # Watch for line that starts with the prefix
- prefix = "Content-Length: "
- if line.startswith(prefix):
- # Decode length of JSON bytes
- length = int(line[len(prefix) :])
- # Skip empty line
- separator = self.recv.readline().decode()
- if separator != "":
- Exception("malformed DAP content header, unexpected line: " + separator)
- # Read JSON bytes
- json_str = self.recv.read(length).decode()
- if self.trace_file:
- self.trace_file.write(
- "%s from adapter:\n%s\n" % (time.time(), json_str)
- )
- # Decode the JSON bytes into a python dictionary
- return json.loads(json_str)
-
- raise Exception("unexpected malformed message from lldb-dap: " + line)
+ def _read_packet_thread(self):
+ try:
+ while True:
+ packet = read_packet(self.recv, trace_file=self.trace_file)
+ # `packet` will be `None` on EOF. We want to pass it down to
+ # handle_recv_packet anyway so the main thread can handle unexpected
+ # termination of lldb-dap and stop waiting for new packets.
+ if not self._handle_recv_packet(packet):
+ break
+ finally:
+ dump_dap_log(self.log_file)
def get_modules(
self, start_module: Optional[int] = None, module_count: Optional[int] = None
@@ -299,6 +310,34 @@ def collect_output(
output += self.get_output(category, clear=clear)
return output
+ def _enqueue_recv_packet(self, packet: Optional[ProtocolMessage]):
+ with self.recv_condition:
+ self.recv_packets.append(packet)
+ self.recv_condition.notify()
+
+ def _handle_recv_packet(self, packet: Optional[ProtocolMessage]) -> bool:
+ """Handles an incoming packet.
+
+ Called by the read thread that is waiting for all incoming packets
+ to store the incoming packet in "self._recv_packets" in a thread safe
+ way. This function will then signal the "self._recv_condition" to
+ indicate a new packet is available.
+
+ Args:
+ packet: A new packet to store.
+
+ Returns:
+ True if the caller should keep calling this function for more
+ packets.
+ """
+ with self._recv_condition:
+ self._recv_packets.append(packet)
+ self._recv_condition.notify()
+ # packet is None on EOF
+ return packet is not None and not (
+ packet["type"] == "response" and packet["command"] == "disconnect"
+ )
+
def _recv_packet(
self,
*,
@@ -322,34 +361,46 @@ def _recv_packet(
The first matching packet for the given predicate, if specified,
otherwise None.
"""
- deadline = time.time() + timeout
-
- while time.time() < deadline:
- packet = self._read_packet(timeout=deadline - time.time())
- if packet is None:
- return None
- self._process_recv_packet(packet)
- if not predicate or predicate(packet):
- return packet
-
- def _process_recv_packet(self, packet) -> None:
+ assert (
+ threading.current_thread != self._recv_thread
+ ), "Must not be called from the _recv_thread"
+
+ def process_until_match():
+ self._process_recv_packets()
+ for i, packet in enumerate(self._pending_packets):
+ if packet is None:
+ # We need to return a truthy value to break out of the
+ # wait_for, use `EOFError` as an indicator of EOF.
+ return EOFError()
+ if predicate and predicate(packet):
+ self._pending_packets.pop(i)
+ return packet
+
+ with self._recv_condition:
+ packet = self._recv_condition.wait_for(process_until_match, timeout)
+ return None if isinstance(packet, EOFError) else packet
+
+ def _process_recv_packets(self) -> None:
"""Process received packets, updating the session state."""
- if packet and ("seq" not in packet or packet["seq"] == 0):
- warnings.warn(
- f"received a malformed packet, expected 'seq != 0' for {packet!r}"
- )
- # Handle events that may modify any stateful properties of
- # the DAP session.
- if packet and packet["type"] == "event":
- self._handle_event(packet)
- elif packet and packet["type"] == "request":
- # Handle reverse requests and keep processing.
- self._handle_reverse_request(packet)
+ with self._recv_condition:
+ for packet in self._recv_packets:
+ if packet and ("seq" not in packet or packet["seq"] == 0):
+ warnings.warn(
+ f"received a malformed packet, expected 'seq != 0' for {packet!r}"
+ )
+ # Handle events that may modify any stateful properties of
+ # the DAP session.
+ if packet and packet["type"] == "event":
+ self._handle_event(packet)
+ elif packet and packet["type"] == "request":
+ # Handle reverse requests and keep processing.
+ self._handle_reverse_request(packet)
+ # Move the packet to the pending queue.
+ self._pending_packets.append(packet)
+ self._recv_packets.clear()
def _handle_event(self, packet: Event) -> None:
"""Handle any events that modify debug session state we track."""
- self.events.append(packet)
-
event = packet["event"]
body: Optional[Dict] = packet.get("body", None)
@@ -402,8 +453,6 @@ def _handle_event(self, packet: Event) -> None:
self.invalidated_event = packet
elif event == "memory":
self.memory_event = packet
- elif event == "module":
- self.module_events.append(packet)
def _handle_reverse_request(self, request: Request) -> None:
if request in self.reverse_requests:
@@ -472,14 +521,18 @@ def send_packet(self, packet: ProtocolMessage) -> int:
Returns the seq number of the request.
"""
- packet["seq"] = self.sequence
- self.sequence += 1
+ # Set the seq for requests.
+ if packet["type"] == "request":
+ packet["seq"] = self.sequence
+ self.sequence += 1
+ else:
+ packet["seq"] = 0
# Encode our command dictionary as a JSON string
json_str = json.dumps(packet, separators=(",", ":"))
if self.trace_file:
- self.trace_file.write("%s to adapter:\n%s\n" % (time.time(), json_str))
+ self.trace_file.write("to adapter:\n%s\n" % (json_str))
length = len(json_str)
if length > 0:
@@ -860,8 +913,6 @@ def request_restart(self, restartArguments=None):
if restartArguments:
command_dict["arguments"] = restartArguments
- # Clear state, the process is about to restart...
- self._process_continued(True)
response = self._send_recv(command_dict)
# Caller must still call wait_for_stopped.
return response
@@ -1428,10 +1479,8 @@ def request_testGetTargetBreakpoints(self):
def terminate(self):
self.send.close()
- self.recv.close()
- self.selector.close()
- if self.log_file:
- dump_dap_log(self.log_file)
+ if self._recv_thread.is_alive():
+ self._recv_thread.join()
def request_setInstructionBreakpoints(self, memory_reference=[]):
breakpoints = []
@@ -1528,7 +1577,6 @@ def launch(
stdout=subprocess.PIPE,
stderr=sys.stderr,
env=adapter_env,
- bufsize=0,
)
if connection is None:
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index fd07324d2ddda..29935bb8046ff 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -416,7 +416,7 @@ def continue_to_next_stop(self):
return self.dap_server.wait_for_stopped()
def continue_to_breakpoint(self, breakpoint_id: str):
- self.continue_to_breakpoints([breakpoint_id])
+ self.continue_to_breakpoints((breakpoint_id))
def continue_to_breakpoints(self, breakpoint_ids):
self.do_continue()
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py
index 7b78541fb4f8e..beab4d6c1f5a6 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py
@@ -81,20 +81,24 @@ def test_breakpoint_events(self):
breakpoint["verified"], "expect foo breakpoint to not be verified"
)
+ # Flush the breakpoint events.
+ self.dap_server.wait_for_breakpoint_events()
+
# Continue to the breakpoint
- self.continue_to_breakpoint(foo_bp_id)
- self.continue_to_next_stop() # foo_bp2
- self.continue_to_breakpoint(main_bp_id)
- self.continue_to_exit()
+ self.continue_to_breakpoints(dap_breakpoint_ids)
- bp_events = [e for e in self.dap_server.events if e["event"] == "breakpoint"]
+ verified_breakpoint_ids = []
+ unverified_breakpoint_ids = []
+ for breakpoint_event in self.dap_server.wait_for_breakpoint_events():
+ breakpoint = breakpoint_event["body"]["breakpoint"]
+ id = breakpoint["id"]
+ if breakpoint["verified"]:
+ verified_breakpoint_ids.append(id)
+ else:
+ unverified_breakpoint_ids.append(id)
- main_bp_events = [
- e for e in bp_events if e["body"]["breakpoint"]["id"] == main_bp_id
- ]
- foo_bp_events = [
- e for e in bp_events if e["body"]["breakpoint"]["id"] == foo_bp_id
- ]
+ self.assertIn(main_bp_id, unverified_breakpoint_ids)
+ self.assertIn(foo_bp_id, unverified_breakpoint_ids)
- self.assertTrue(main_bp_events)
- self.assertTrue(foo_bp_events)
+ self.assertIn(main_bp_id, verified_breakpoint_ids)
+ self.assertIn(foo_bp_id, verified_breakpoint_ids)
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index dc6bf38303204..ca881f1d817c5 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -156,7 +156,6 @@ def test_debuggerRoot(self):
self.build_and_launch(
program, debuggerRoot=program_parent_dir, initCommands=commands
)
- self.continue_to_exit()
output = self.get_console()
self.assertTrue(output and len(output) > 0, "expect console output")
lines = output.splitlines()
@@ -172,6 +171,7 @@ def test_debuggerRoot(self):
% (program_parent_dir, line[len(prefix) :]),
)
self.assertTrue(found, "verified lldb-dap working directory")
+ self.continue_to_exit()
def test_sourcePath(self):
"""
@@ -642,6 +642,7 @@ def test_stdio_redirection(self):
@skipIfAsan
@skipIfWindows
@skipIf(oslist=["linux"], archs=no_match(["x86_64"]))
+ @skipIfBuildType(["debug"])
def test_stdio_redirection_and_console(self):
"""
Test stdio redirection and console.
diff --git a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py
index 9d1d17b704f76..1f4afabbd161e 100644
--- a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py
+++ b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py
@@ -1,58 +1,58 @@
-"""
-Test 'module' events for dynamically loaded libraries.
-"""
-
+import dap_server
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
import lldbdap_testcase
+import re
class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase):
- def lookup_module_id(self, name):
- """Returns the identifier for the first module event starting with the given name."""
- for event in self.dap_server.module_events:
- if self.get_dict_value(event, ["body", "module", "name"]).startswith(name):
- return self.get_dict_value(event, ["body", "module", "id"])
- self.fail(f"No module events matching name={name}")
-
- def module_events(self, id):
- """Finds all module events by identifier."""
- return [
- event
- for event in self.dap_server.module_events
- if self.get_dict_value(event, ["body", "module", "id"]) == id
- ]
-
- def module_reasons(self, events):
- """Returns the list of 'reason' values from the given events."""
- return [event["body"]["reason"] for event in events]
-
@skipIfWindows
def test_module_event(self):
- """
- Test that module events are fired on target load and when the list of
- dynamic libraries updates while running.
- """
program = self.getBuildArtifact("a.out")
self.build_and_launch(program)
- # We can analyze the order of events after the process exits.
- self.continue_to_exit()
- a_out_id = self.lookup_module_id("a.out")
- a_out_events = self.module_events(id=a_out_id)
+ source = "main.cpp"
+ breakpoint1_line = line_number(source, "// breakpoint 1")
+ breakpoint2_line = line_number(source, "// breakpoint 2")
+ breakpoint3_line = line_number(source, "// breakpoint 3")
- self.assertIn(
- "new",
- self.module_reasons(a_out_events),
- "Expected a.out to load during the debug session.",
+ breakpoint_ids = self.set_source_breakpoints(
+ source, [breakpoint1_line, breakpoint2_line, breakpoint3_line]
)
+ self.continue_to_breakpoints(breakpoint_ids)
+
+ # We're now stopped at breakpoint 1 before the dlopen. Flush all the module events.
+ event = self.dap_server.wait_for_event(["module"])
+ while event is not None:
+ event = self.dap_server.wait_for_event(["module"])
+
+ # Continue to the second breakpoint, before the dlclose.
+ self.continue_to_breakpoints(breakpoint_ids)
+
+ # Make sure we got a module event for libother.
+ event = self.dap_server.wait_for_event(["module"])
+ self.assertIsNotNone(event, "didn't get a module event")
+ module_name = event["body"]["module"]["name"]
+ module_id = event["body"]["module"]["id"]
+ self.assertEqual(event["body"]["reason"], "new")
+ self.assertIn("libother", module_name)
+
+ # Continue to the third breakpoint, after the dlclose.
+ self.continue_to_breakpoints(breakpoint_ids)
+
+ # Make sure we got a module event for libother.
+ event = self.dap_server.wait_for_event(["module"])
+ self.assertIsNotNone(event, "didn't get a module event")
+ reason = event["body"]["reason"]
+ self.assertEqual(reason, "removed")
+ self.assertEqual(event["body"]["module"]["id"], module_id)
+
+ # The removed module event should omit everything but the module id and name
+ # as they are required fields.
+ module_data = event["body"]["module"]
+ required_keys = ["id", "name"]
+ self.assertListEqual(list(module_data.keys()), required_keys)
+ self.assertEqual(module_data["name"], "", "expects empty name.")
- libother_id = self.lookup_module_id(
- "libother." # libother.so or libother.dylib based on OS.
- )
- libother_events = self.module_events(id=libother_id)
- self.assertEqual(
- self.module_reasons(libother_events),
- ["new", "removed"],
- "Expected libother to be loaded then unloaded during the debug session.",
- )
+ self.continue_to_exit()
diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
index 2d00c512721c6..0ed53dac5d869 100644
--- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
+++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
@@ -64,18 +64,19 @@ def check_symbols_loaded_with_size():
self.assertEqual(program, program_module["path"])
self.assertIn("addressRange", program_module)
- self.continue_to_exit()
-
# Collect all the module names we saw as events.
module_new_names = []
module_changed_names = []
- for module_event in self.dap_server.module_events:
+ module_event = self.dap_server.wait_for_event(["module"])
+ while module_event is not None:
reason = module_event["body"]["reason"]
if reason == "new":
module_new_names.append(module_event["body"]["module"]["name"])
elif reason == "changed":
module_changed_names.append(module_event["body"]["module"]["name"])
+ module_event = self.dap_server.wait_for_event(["module"])
+
# Make sure we got an event for every active module.
self.assertNotEqual(len(module_new_names), 0)
for module in active_modules:
@@ -85,6 +86,7 @@ def check_symbols_loaded_with_size():
# symbols got added.
self.assertNotEqual(len(module_changed_names), 0)
self.assertIn(program_module["name"], module_changed_names)
+ self.continue_to_exit()
@skipIfWindows
def test_modules(self):
diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py
index fa62ec243f5c5..e1ad1425a993d 100644
--- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py
+++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py
@@ -30,11 +30,7 @@ def verify_stopped_on_entry(self, stopped_events: List[Dict[str, Any]]):
if reason == "entry":
seen_stopped_event += 1
- self.assertEqual(
- seen_stopped_event,
- 1,
- f"expect only one stopped entry event in {stopped_events}",
- )
+ self.assertEqual(seen_stopped_event, 1, "expect only one stopped entry event.")
@skipIfAsan
@skipIfWindows
@@ -96,13 +92,11 @@ def test_stopOnEntry(self):
self.build_and_launch(program, console="integratedTerminal", stopOnEntry=True)
[bp_main] = self.set_function_breakpoints(["main"])
- self.dap_server.request_configurationDone()
- stopped_threads = list(self.dap_server.thread_stop_reasons.values())
+ self.dap_server.request_continue() # sends configuration done
+ stopped_events = self.dap_server.wait_for_stopped()
# We should be stopped at the entry point.
- self.assertEqual(
- len(stopped_threads), 1, "Expected the main thread to be stopped on entry."
- )
- self.assertEqual(stopped_threads[0]["reason"], "entry")
+ self.assertGreaterEqual(len(stopped_events), 0, "expect stopped events")
+ self.verify_stopped_on_entry(stopped_events)
# Then, if we continue, we should hit the breakpoint at main.
self.dap_server.request_continue()
@@ -111,12 +105,8 @@ def test_stopOnEntry(self):
# Restart and check that we still get a stopped event before reaching
# main.
self.dap_server.request_restart()
- stopped_threads = list(self.dap_server.thread_stop_reasons.values())
- # We should be stopped at the entry point.
- self.assertEqual(
- len(stopped_threads), 1, "Expected the main thread to be stopped on entry."
- )
- self.assertEqual(stopped_threads[0]["reason"], "entry")
+ stopped_events = self.dap_server.wait_for_stopped()
+ self.verify_stopped_on_entry(stopped_events)
# continue to main
self.dap_server.request_continue()
diff --git a/lldb/test/API/tools/lldb-dap/send-event/TestDAP_sendEvent.py b/lldb/test/API/tools/lldb-dap/send-event/TestDAP_sendEvent.py
index 0184020589176..a01845669666f 100644
--- a/lldb/test/API/tools/lldb-dap/send-event/TestDAP_sendEvent.py
+++ b/lldb/test/API/tools/lldb-dap/send-event/TestDAP_sendEvent.py
@@ -32,7 +32,7 @@ def test_send_event(self):
],
)
self.set_source_breakpoints(source, [breakpoint_line])
- self.do_continue()
+ self.continue_to_next_stop()
custom_event = self.dap_server.wait_for_event(
filter=["my-custom-event-no-body"]
diff --git a/llvm/docs/DeveloperPolicy.rst b/llvm/docs/DeveloperPolicy.rst
index 45f2df20984e6..9135406c2e2a1 100644
--- a/llvm/docs/DeveloperPolicy.rst
+++ b/llvm/docs/DeveloperPolicy.rst
@@ -1189,6 +1189,55 @@ Suggested disclaimer for the project README and the main project web page:
necessarily a reflection of the completeness or stability of the code, it
does indicate that the project is not yet endorsed as a component of LLVM.
+Adding or enabling a new LLVM pass
+----------------------------------
+
+The guidelines here are primarily targeted at the enablement of new major
+passes in the target-independent optimization pipeline. Small additions, or
+backend-specific passes, require a lesser degree of care. Before creating a new
+pass, consider whether the functionality can be integrated into an existing
+pass first. This is often both faster and more powerful.
+
+When adding a new pass, the goal should be to enable it as part of the default
+optimization pipeline as early as possible and then continue development
+incrementally. (This does not apply to passes that are only relevant for
+specific uses of LLVM, such as GC support passes.)
+
+The recommended workflow is:
+
+1. Implement a basic version of the pass and add it to the pass pipeline behind
+ a flag that is disabled by default. The initial version should focus on
+ handling simple cases correctly and efficiently.
+2. Enable the pass by default. Separating this step allows easily disabling the
+ pass if issues are encountered, without having to revert the entire
+ implementation.
+3. Incrementally extend the pass with new functionality. As the pass is already
+ enabled, it becomes easier to identify the specific change that has caused a
+ regression in correctness, optimization quality or compile-time.
+
+When enabling a pass, certain requirements must be met (in no particular order):
+
+ * **Maintenance:** The pass (and any analyses it depends on) must have at
+ least one maintainer.
+ * **Usefulness:** There should be evidence that the pass improves performance
+ (or whatever metric it optimizes for) on real-world workloads. Improvements
+ seen only on synthetic benchmarks may be insufficient.
+ * **Compile-Time:** The pass should not have a large impact on compile-time,
+ where the evaluation of what "large" means is up to reviewer discretion, and
+ may differ based on the value the pass provides. In any case, it is expected
+ that a concerted effort has been made to mitigate the compile-time impact,
+ both for the average case, and for pathological cases.
+ * **Correctness:** The pass should have no known correctness issues (except
+ global correctness issues that affect all of LLVM). If an old pass is being
+ enabled (rather than implementing a new one incrementally), additional due
+ diligence is required. The pass should be fully reviewed to ensure that it
+ still complies with current quality standards. Fuzzing with disabled
+ profitability checks may help gain additional confidence in the
+ implementation.
+
+If non-trivial issues are found in a newly enabled pass, it may be temporarily
+disabled again, until the issues have been resolved.
+
.. _copyright-license-patents:
Copyright, License, and Patents
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
index c69b6f736651e..86207265021c5 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Implements ExecutorProcessControl::MemoryAccess by making calls to
+// Implements the MemoryAccess interface by making calls to
// ExecutorProcessControl::callWrapperAsync.
//
// This simplifies the implementaton of new ExecutorProcessControl instances,
@@ -19,6 +19,7 @@
#define LLVM_EXECUTIONENGINE_ORC_EPCGENERICMEMORYACCESS_H
#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/MemoryAccess.h"
namespace llvm {
namespace orc {
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index 87b95200b2459..d7f0e3a3d49da 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -1167,6 +1167,14 @@ struct ThreadsT {
using EmptyTrait = std::true_type;
};
+// V6.0: [14.8] `threadset` clause
+template //
+struct ThreadsetT {
+ ENUM(ThreadsetPolicy, Omp_Pool, Omp_Team);
+ using WrapperTrait = std::true_type;
+ ThreadsetPolicy v;
+};
+
// V5.2: [5.9.1] `to` clause
template //
struct ToT {
@@ -1352,9 +1360,9 @@ using WrapperClausesT = std::variant<
ProcBindT, ReverseOffloadT, SafelenT,
SelfMapsT, SeverityT, SharedT, SimdlenT,
SizesT, PermutationT, ThreadLimitT,
- UnifiedAddressT, UnifiedSharedMemoryT, UniformT,
- UpdateT, UseDeviceAddrT, UseDevicePtrT,
- UsesAllocatorsT>;
+ ThreadsetT, UnifiedAddressT,
+ UnifiedSharedMemoryT, UniformT, UpdateT,
+ UseDeviceAddrT, UseDevicePtrT, UsesAllocatorsT>;
template
using UnionOfAllClausesT = typename type::Union< //
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 61a1a05f6e904..208609f64f418 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -539,6 +539,10 @@ def OMPC_GroupPrivate : Clause<[Spelling<"groupprivate">]> {
def OMPC_Threads : Clause<[Spelling<"threads">]> {
let clangClass = "OMPThreadsClause";
}
+def OMPC_Threadset : Clause<[Spelling<"threadset">]> {
+ let clangClass = "OMPThreadsetClause";
+ let flangClass = "OmpThreadsetClause";
+}
def OMPC_To : Clause<[Spelling<"to">]> {
let clangClass = "OMPToClause";
let flangClass = "OmpToClause";
@@ -1254,6 +1258,7 @@ def OMP_Task : Directive<[Spelling<"task">]> {
VersionedClause,
VersionedClause,
VersionedClause,
+ VersionedClause,
VersionedClause,
VersionedClause,
];
@@ -1297,6 +1302,7 @@ def OMP_TaskLoop : Directive<[Spelling<"taskloop">]> {
VersionedClause,
VersionedClause,
VersionedClause,
+ VersionedClause,
VersionedClause,
VersionedClause,
];
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
index e09eea47525ee..6bfe229e0f441 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
@@ -1347,6 +1347,9 @@ void AMDGPUPassConfig::addIRPasses() {
isPassEnabled(EnableImageIntrinsicOptimizer))
addPass(createAMDGPUImageIntrinsicOptimizerPass(&TM));
+ if (EnableUniformIntrinsicCombine)
+ addPass(createAMDGPUUniformIntrinsicCombineLegacyPass());
+
// This can be disabled by passing ::Disable here or on the command line
// with --expand-variadics-override=disable.
addPass(createExpandVariadicsPass(ExpandVariadicsMode::Lowering));
@@ -2098,6 +2101,8 @@ void AMDGPUCodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const {
if (isPassEnabled(EnableImageIntrinsicOptimizer))
addPass(AMDGPUImageIntrinsicOptimizerPass(TM));
+ if (EnableUniformIntrinsicCombine)
+ addPass(AMDGPUUniformIntrinsicCombinePass());
// This can be disabled by passing ::Disable here or on the command line
// with --expand-variadics-override=disable.
addPass(ExpandVariadicsPass(ExpandVariadicsMode::Lowering));
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index e043d072a7638..08be5df9872b7 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1534,8 +1534,8 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
bool SrcNotDom = false;
auto CaptureTrackingWithModRef =
- [&](Instruction *AI,
- function_ref ModRefCallback) -> bool {
+ [&](Instruction *AI, function_ref ModRefCallback,
+ bool &AddressCaptured) -> bool {
SmallVector Worklist;
Worklist.push_back(AI);
unsigned MaxUsesToExplore = getDefaultMaxUsesToExploreForCaptureTracking();
@@ -1559,8 +1559,9 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
if (!Visited.insert(&U).second)
continue;
UseCaptureInfo CI = DetermineUseCaptureKind(U, AI);
- if (capturesAnything(CI.UseCC))
+ if (capturesAnyProvenance(CI.UseCC))
return false;
+ AddressCaptured |= capturesAddress(CI.UseCC);
if (UI->mayReadOrWriteMemory()) {
if (UI->isLifetimeStartOrEnd()) {
@@ -1627,7 +1628,9 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
return true;
};
- if (!CaptureTrackingWithModRef(DestAlloca, DestModRefCallback))
+ bool DestAddressCaptured = false;
+ if (!CaptureTrackingWithModRef(DestAlloca, DestModRefCallback,
+ DestAddressCaptured))
return false;
// Bailout if Dest may have any ModRef before Store.
if (!ReachabilityWorklist.empty() &&
@@ -1653,7 +1656,14 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
return true;
};
- if (!CaptureTrackingWithModRef(SrcAlloca, SrcModRefCallback))
+ bool SrcAddressCaptured = false;
+ if (!CaptureTrackingWithModRef(SrcAlloca, SrcModRefCallback,
+ SrcAddressCaptured))
+ return false;
+
+ // If both the source and destination address are captured, the fact that they
+ // are no longer two separate allocations may be observed.
+ if (DestAddressCaptured && SrcAddressCaptured)
return false;
// We can do the transformation. First, move the SrcAlloca to the start of the
diff --git a/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll
new file mode 100644
index 0000000000000..43f66dd7d0974
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/gcd-miv-overflow.ll
@@ -0,0 +1,66 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -disable-output "-passes=print" 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
+; RUN: opt < %s -disable-output "-passes=print" -da-enable-dependence-test=gcd-miv 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-GCD-MIV
+
+; offset0 = 4;
+; offset1 = 0;
+; for (i = 0; i < 100; i++) {
+; A[offset0] = 1;
+; A[offset1] = 2;
+; offset0 += 3*m;
+; offset1 += 3;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. E.g., consider `m` is 12297829382473034411, which
+; is a modular multiplicative inverse of 3 under modulo 2^64. Then `offset0` is
+; effectively `i + 4`, so accesses will be as follows:
+;
+; - A[offset0] : A[4], A[5], A[6], ...
+; - A[offset1] : A[0], A[3], A[6], ...
+;
+; The root cause is that DA interprets `3*m` in non-modular arithmetic, which
+; isn't necessarily true due to overflow.
+;
+define void @gcdmiv_coef_ovfl(ptr %A, i64 %m) {
+; CHECK-ALL-LABEL: 'gcdmiv_coef_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+;
+; CHECK-GCD-MIV-LABEL: 'gcdmiv_coef_ovfl'
+; CHECK-GCD-MIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-GCD-MIV-NEXT: da analyze - consistent output [*]!
+; CHECK-GCD-MIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-GCD-MIV-NEXT: da analyze - none!
+; CHECK-GCD-MIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-GCD-MIV-NEXT: da analyze - consistent output [*]!
+;
+entry:
+ %step = mul i64 3, %m
+ br label %loop
+
+loop:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
+ %offset.0 = phi i64 [ 4, %entry ] , [ %offset.0.next, %loop ]
+ %offset.1 = phi i64 [ 0, %entry ] , [ %offset.1.next, %loop ]
+ %gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset.0
+ %gep.1 = getelementptr inbounds i8, ptr %A, i64 %offset.1
+ store i8 1, ptr %gep.0
+ store i8 2, ptr %gep.1
+ %i.inc = add nuw nsw i64 %i, 1
+ %offset.0.next = add nsw i64 %offset.0, %step
+ %offset.1.next = add nsw i64 %offset.1, 3
+ %ec = icmp eq i64 %i.inc, 100
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/Analysis/DependenceAnalysis/strong-siv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/strong-siv-overflow.ll
new file mode 100644
index 0000000000000..bf0fafcbfd6c9
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/strong-siv-overflow.ll
@@ -0,0 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -disable-output "-passes=print" 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
+; RUN: opt < %s -disable-output "-passes=print" -da-enable-dependence-test=strong-siv 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-STRONG-SIV
+
+; for (i = 0; i < (1LL << 62); i++) {
+; if (0 <= 2*i - 2)
+; A[2*i - 2] = 1;
+;
+; if (0 <= 2*i - 4)
+; A[2*i - 4] = 2;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. For example, each store will access A[0] when i
+; is 1 and 2 respectively.
+; The root cause is that the product of the BTC and the coefficient
+; ((1LL << 62) - 1 and 2) overflows in a signed sense.
+define void @strongsiv_const_ovfl(ptr %A) {
+; CHECK-LABEL: 'strongsiv_const_ovfl'
+; CHECK-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-NEXT: da analyze - none!
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+ %offset.0 = phi i64 [ -2, %entry ], [ %offset.0.next, %loop.latch ]
+ %offset.1 = phi i64 [ -4, %entry ], [ %offset.1.next, %loop.latch ]
+ %ec = icmp eq i64 %i, 4611686018427387904
+ br i1 %ec, label %exit, label %loop.body
+
+loop.body:
+ %cond.0 = icmp sge i64 %offset.0, 0
+ %cond.1 = icmp sge i64 %offset.1, 0
+ br i1 %cond.0, label %if.then.0, label %loop.middle
+
+if.then.0:
+ %gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset.0
+ store i8 1, ptr %gep.0
+ br label %loop.middle
+
+loop.middle:
+ br i1 %cond.1, label %if.then.1, label %loop.latch
+
+if.then.1:
+ %gep.1 = getelementptr inbounds i8, ptr %A, i64 %offset.1
+ store i8 2, ptr %gep.1
+ br label %loop.latch
+
+loop.latch:
+ %i.inc = add nuw nsw i64 %i, 1
+ %offset.0.next = add nsw i64 %offset.0, 2
+ %offset.1.next = add nsw i64 %offset.1, 2
+ br label %loop.header
+
+exit:
+ ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-ALL: {{.*}}
+; CHECK-STRONG-SIV: {{.*}}
diff --git a/llvm/test/Analysis/DependenceAnalysis/symbolic-rdiv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/symbolic-rdiv-overflow.ll
new file mode 100644
index 0000000000000..c5ff9884a0c62
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/symbolic-rdiv-overflow.ll
@@ -0,0 +1,137 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -disable-output "-passes=print" 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
+; RUN: opt < %s -disable-output "-passes=print" -da-enable-dependence-test=symbolic-rdiv 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-SYMBOLIC-RDIV
+
+; for (i = 0; i < (1LL << 62); i++) {
+; if (0 <= 2*i - 2)
+; A[2*i - 2] = 1;
+; A[i] = 2;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. For example, each store will access A[0] when i
+; is 1 and 0 respectively.
+; The root cause is that the product of the BTC and the coefficient
+; ((1LL << 62) - 1 and 2) overflows in a signed sense.
+define void @symbolicrdiv_prod_ovfl(ptr %A) {
+; CHECK-ALL-LABEL: 'symbolicrdiv_prod_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+;
+; CHECK-SYMBOLIC-RDIV-LABEL: 'symbolicrdiv_prod_ovfl'
+; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - none!
+; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - none!
+; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - consistent output [*]!
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+ %offset = phi i64 [ -2, %entry ], [ %offset.next, %loop.latch ]
+ %ec = icmp eq i64 %i, 4611686018427387904
+ br i1 %ec, label %exit, label %loop.body
+
+loop.body:
+ %cond = icmp sge i64 %offset, 0
+ br i1 %cond, label %if.then, label %loop.latch
+
+if.then:
+ %gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset
+ store i8 1, ptr %gep.0
+ br label %loop.latch
+
+loop.latch:
+ %gep.1 = getelementptr inbounds i8, ptr %A, i64 %i
+ store i8 2, ptr %gep.1
+ %i.inc = add nuw nsw i64 %i, 1
+ %offset.next = add nsw i64 %offset, 2
+ br label %loop.header
+
+exit:
+ ret void
+}
+
+; offset0 = -4611686018427387904; // -2^62
+; offset1 = 4611686018427387904; // 2^62
+; for (i = 0; i < (1LL << 62) - 100; i++) {
+; if (0 <= offset0)
+; A[offset0] = 1;
+; if (0 <= offset1)
+; A[offset1] = 2;
+; offset0 += 2;
+; offset1 -= 1;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. For example,
+;
+; memory access | i == 2^61 | i == 2^61 + 2^59 | i == 2^61 + 2^60
+; -------------------------|-----------|------------------|-------------------
+; A[2*i - 2^62] (offset0) | | A[2^60] | A[2^61]
+; A[-i + 2^62] (offset1) | A[2^61] | | A[2^60]
+;
+; The root cause is that the calculation of the differenct between the two
+; constants (-2^62 and 2^62) overflows in a signed sense.
+define void @symbolicrdiv_delta_ovfl(ptr %A) {
+; CHECK-ALL-LABEL: 'symbolicrdiv_delta_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+;
+; CHECK-SYMBOLIC-RDIV-LABEL: 'symbolicrdiv_delta_ovfl'
+; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - consistent output [*]!
+; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - none!
+; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - consistent output [*]!
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+ %offset.0 = phi i64 [ -4611686018427387904, %entry ], [ %offset.0.next, %loop.latch ]
+ %offset.1 = phi i64 [ 4611686018427387904, %entry ], [ %offset.1.next, %loop.latch ]
+ %cond.0 = icmp sge i64 %offset.0, 0
+ %cond.1 = icmp sge i64 %offset.1, 0
+ br i1 %cond.0, label %if.then.0, label %loop.middle
+
+if.then.0:
+ %gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset.0
+ store i8 1, ptr %gep.0
+ br label %loop.middle
+
+loop.middle:
+ br i1 %cond.1, label %if.then.1, label %loop.latch
+
+if.then.1:
+ %gep.1 = getelementptr inbounds i8, ptr %A, i64 %offset.1
+ store i8 2, ptr %gep.1
+ br label %loop.latch
+
+loop.latch:
+ %i.inc = add nuw nsw i64 %i, 1
+ %offset.0.next = add nsw i64 %offset.0, 2
+ %offset.1.next = sub nsw i64 %offset.1, 1
+ %ec = icmp eq i64 %i.inc, 4611686018427387804 ; 2^62 - 100
+ br i1 %ec, label %exit, label %loop.header
+
+exit:
+ ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
new file mode 100644
index 0000000000000..ba57c7bf5736a
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
@@ -0,0 +1,125 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -disable-output "-passes=print" 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
+; RUN: opt < %s -disable-output "-passes=print" -da-enable-dependence-test=weak-crossing-siv 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-WEAK-CROSSING-SIV
+
+; max_i = INT64_MAX/3 // 3074457345618258602
+; for (long long i = 0; i <= max_i; i++) {
+; A[-3*i + INT64_MAX] = 0;
+; if (i)
+; A[3*i - 2] = 1;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between
+; `A[-3*i + INT64_MAX]` and `A[3*i - 2]`, but it does exist. For example,
+;
+; memory access | i == 1 | i == max_i
+; ---------------------|------------------|------------------
+; A[-3*i + INT64_MAX] | A[INT64_MAX - 3] | A[1]
+; A[3*i - 2] | A[1] | A[INT64_MAX - 3]
+;
+; The root cause is that the calculation of the differenct between the two
+; constants (INT64_MAX and -2) triggers an overflow.
+
+define void @weakcorssing_delta_ovfl(ptr %A) {
+; CHECK-ALL-LABEL: 'weakcorssing_delta_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+;
+; CHECK-WEAK-CROSSING-SIV-LABEL: 'weakcorssing_delta_ovfl'
+; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
+; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - none!
+; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+ %subscript.0 = phi i64 [ 9223372036854775807, %entry ], [ %subscript.0.next, %loop.latch ]
+ %subscript.1 = phi i64 [ -2, %entry ], [ %subscript.1.next, %loop.latch ]
+ %idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0
+ store i8 0, ptr %idx.0
+ %cond.store = icmp ne i64 %i, 0
+ br i1 %cond.store, label %if.store, label %loop.latch
+
+if.store:
+ %idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1
+ store i8 1, ptr %idx.1
+ br label %loop.latch
+
+loop.latch:
+ %i.inc = add nuw nsw i64 %i, 1
+ %subscript.0.next = add nsw i64 %subscript.0, -3
+ %subscript.1.next = add nsw i64 %subscript.1, 3
+ %ec = icmp sgt i64 %i.inc, 3074457345618258602
+ br i1 %ec, label %exit, label %loop.header
+
+exit:
+ ret void
+}
+
+; max_i = INT64_MAX/3 // 3074457345618258602
+; for (long long i = 0; i <= max_i; i++) {
+; A[-3*i + INT64_MAX] = 0;
+; A[3*i + 1] = 1;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between
+; `A[-3*i + INT64_MAX]` and `A[3*i - 2]`, but it does exist. For example,
+;
+; memory access | i == 0 | i == 1 | i == max_i - 1 | i == max_i
+; ---------------------|--------|------------------|----------------|------------------
+; A[-3*i + INT64_MAX] | | A[INT64_MAX - 3] | A[1] |
+; A[3*i + 1] | A[1] | | | A[INT64_MAX - 3]
+;
+; The root cause is that the product of the BTC, the coefficient, and 2
+; triggers an overflow.
+;
+define void @weakcorssing_prod_ovfl(ptr %A) {
+; CHECK-ALL-LABEL: 'weakcorssing_prod_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+;
+; CHECK-WEAK-CROSSING-SIV-LABEL: 'weakcorssing_prod_ovfl'
+; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
+; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - none!
+; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
+;
+entry:
+ br label %loop
+
+loop:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
+ %subscript.0 = phi i64 [ 9223372036854775807, %entry ], [ %subscript.0.next, %loop ]
+ %subscript.1 = phi i64 [ 1, %entry ], [ %subscript.1.next, %loop ]
+ %idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0
+ %idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1
+ store i8 0, ptr %idx.0
+ store i8 1, ptr %idx.1
+ %i.inc = add nuw nsw i64 %i, 1
+ %subscript.0.next = add nsw i64 %subscript.0, -3
+ %subscript.1.next = add nsw i64 %subscript.1, 3
+ %ec = icmp sgt i64 %i.inc, 3074457345618258602
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll
new file mode 100644
index 0000000000000..6317c387858d3
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll
@@ -0,0 +1,122 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -disable-output "-passes=print" 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
+; RUN: opt < %s -disable-output "-passes=print" -da-enable-dependence-test=weak-zero-siv 2>&1 \
+; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-WEAK-ZERO-SIV
+
+; for (i = 0; i < (1LL << 62); i++) {
+; if (0 <= 2*i - 2)
+; A[2*i - 2] = 1;
+; A[2] = 2;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. The root cause is that the product of the BTC and
+; the coefficient ((1LL << 62) - 1 and 2) overflows in a signed sense.
+;
+define void @weakzero_dst_siv_prod_ovfl(ptr %A) {
+; CHECK-ALL-LABEL: 'weakzero_dst_siv_prod_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - consistent output [S]!
+;
+; CHECK-WEAK-ZERO-SIV-LABEL: 'weakzero_dst_siv_prod_ovfl'
+; CHECK-WEAK-ZERO-SIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-WEAK-ZERO-SIV-NEXT: da analyze - consistent output [*]!
+; CHECK-WEAK-ZERO-SIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-WEAK-ZERO-SIV-NEXT: da analyze - none!
+; CHECK-WEAK-ZERO-SIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-WEAK-ZERO-SIV-NEXT: da analyze - consistent output [S]!
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+ %offset = phi i64 [ -2, %entry ], [ %offset.next, %loop.latch ]
+ %ec = icmp eq i64 %i, 4611686018427387904
+ br i1 %ec, label %exit, label %loop.body
+
+loop.body:
+ %cond = icmp sge i64 %offset, 0
+ br i1 %cond, label %if.then, label %loop.latch
+
+if.then:
+ %gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset
+ store i8 1, ptr %gep.0
+ br label %loop.latch
+
+loop.latch:
+ %gep.1 = getelementptr inbounds i8, ptr %A, i64 2
+ store i8 2, ptr %gep.1
+ %i.inc = add nuw nsw i64 %i, 1
+ %offset.next = add nsw i64 %offset, 2
+ br label %loop.header
+
+exit:
+ ret void
+}
+
+; for (i = 0; i < n; i++) {
+; if (0 <= 2*i - 1)
+; A[2*i - 1] = 1;
+; A[INT64_MAX] = 2;
+; }
+;
+; FIXME: DependenceAnalysis currently detects no dependency between the two
+; stores, but it does exist. When `%n` is 2^62, the value of `%offset` will be
+; the same as INT64_MAX at the last iteration.
+; The root cause is that the calculation of the difference between the two
+; constants (INT64_MAX and -1) overflows in a signed sense.
+;
+define void @weakzero_dst_siv_delta_ovfl(ptr %A, i64 %n) {
+; CHECK-ALL-LABEL: 'weakzero_dst_siv_delta_ovfl'
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - none!
+; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-ALL-NEXT: da analyze - consistent output [S]!
+;
+; CHECK-WEAK-ZERO-SIV-LABEL: 'weakzero_dst_siv_delta_ovfl'
+; CHECK-WEAK-ZERO-SIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
+; CHECK-WEAK-ZERO-SIV-NEXT: da analyze - consistent output [*]!
+; CHECK-WEAK-ZERO-SIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-WEAK-ZERO-SIV-NEXT: da analyze - none!
+; CHECK-WEAK-ZERO-SIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
+; CHECK-WEAK-ZERO-SIV-NEXT: da analyze - consistent output [S]!
+;
+entry:
+ %guard = icmp sgt i64 %n, 0
+ br i1 %guard, label %loop.header, label %exit
+
+loop.header:
+ %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
+ %offset = phi i64 [ -2, %entry ], [ %offset.next, %loop.latch ]
+ %ec = icmp eq i64 %i, %n
+ br i1 %ec, label %exit, label %loop.body
+
+loop.body:
+ %cond = icmp sge i64 %offset, 0
+ br i1 %cond, label %if.then, label %loop.latch
+
+if.then:
+ %gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset
+ store i8 1, ptr %gep.0
+ br label %loop.latch
+
+loop.latch:
+ %gep.1 = getelementptr inbounds i8, ptr %A, i64 9223372036854775807
+ store i8 2, ptr %gep.1
+ %i.inc = add nuw nsw i64 %i, 1
+ %offset.next = add nsw i64 %offset, 2
+ br label %loop.header
+
+exit:
+ ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/arm64-srl-and.ll b/llvm/test/CodeGen/AArch64/arm64-srl-and.ll
index b58f6ba96a5b8..330f27bd6c0cd 100644
--- a/llvm/test/CodeGen/AArch64/arm64-srl-and.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-srl-and.ll
@@ -1,22 +1,38 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-linux-gnu -O3 < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -O3 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-linux-gnu -O3 -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
; This used to miscompile:
; The 16-bit -1 should not become 32-bit -1 (sub w8, w8, #1).
@g = global i16 0, align 4
define i32 @srl_and() {
-; CHECK-LABEL: srl_and:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: adrp x8, :got:g
-; CHECK-NEXT: mov w9, #50
-; CHECK-NEXT: ldr x8, [x8, :got_lo12:g]
-; CHECK-NEXT: ldrh w8, [x8]
-; CHECK-NEXT: eor w8, w8, w9
-; CHECK-NEXT: mov w9, #65535
-; CHECK-NEXT: add w8, w8, w9
-; CHECK-NEXT: and w0, w8, w8, lsr #16
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: srl_and:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: adrp x8, :got:g
+; CHECK-SD-NEXT: mov w9, #50 // =0x32
+; CHECK-SD-NEXT: ldr x8, [x8, :got_lo12:g]
+; CHECK-SD-NEXT: ldrh w8, [x8]
+; CHECK-SD-NEXT: eor w8, w8, w9
+; CHECK-SD-NEXT: mov w9, #65535 // =0xffff
+; CHECK-SD-NEXT: add w8, w8, w9
+; CHECK-SD-NEXT: and w0, w8, w8, lsr #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: srl_and:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: adrp x8, :got:g
+; CHECK-GI-NEXT: mov w9, #50 // =0x32
+; CHECK-GI-NEXT: ldr x8, [x8, :got_lo12:g]
+; CHECK-GI-NEXT: ldrh w8, [x8]
+; CHECK-GI-NEXT: eor w8, w8, w9
+; CHECK-GI-NEXT: mov w9, #65535 // =0xffff
+; CHECK-GI-NEXT: add w8, w9, w8, uxth
+; CHECK-GI-NEXT: and w9, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, w9
+; CHECK-GI-NEXT: cset w8, ne
+; CHECK-GI-NEXT: and w0, w9, w8
+; CHECK-GI-NEXT: ret
entry:
%0 = load i16, ptr @g, align 4
%1 = xor i16 %0, 50
@@ -29,3 +45,5 @@ entry:
ret i32 %and
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll b/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
index c3fdc7db2abbe..8438f0b03179c 100644
--- a/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefix=CHECK
+; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-unknown -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
; We are looking for the following pattern here:
; (X & (C l>> Y)) ==/!= 0
@@ -13,12 +14,21 @@
; i8 scalar
define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x80
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x80
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #128 // =0x80
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i8 128, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 0
@@ -26,12 +36,21 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
}
define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i8 1, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 0
@@ -39,12 +58,21 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
}
define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x18
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x18
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #24 // =0x18
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i8 24, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 0
@@ -54,12 +82,21 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
; i16 scalar
define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: scalar_i16_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x8000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i16_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x8000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i16_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #32768 // =0x8000
+; CHECK-GI-NEXT: and w9, w1, #0xffff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i16 32768, %y
%t1 = and i16 %t0, %x
%res = icmp eq i16 %t1, 0
@@ -67,12 +104,21 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
}
define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: scalar_i16_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i16_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i16_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: and w9, w1, #0xffff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i16 1, %y
%t1 = and i16 %t0, %x
%res = icmp eq i16 %t1, 0
@@ -80,12 +126,21 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
}
define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: scalar_i16_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0xff0
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i16_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0xff0
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i16_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #4080 // =0xff0
+; CHECK-GI-NEXT: and w9, w1, #0xffff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i16 4080, %y
%t1 = and i16 %t0, %x
%res = icmp eq i16 %t1, 0
@@ -95,12 +150,20 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
; i32 scalar
define i1 @scalar_i32_signbit_eq(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: scalar_i32_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x80000000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i32_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x80000000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i32_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-2147483648 // =0x80000000
+; CHECK-GI-NEXT: lsr w8, w8, w1
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i32 2147483648, %y
%t1 = and i32 %t0, %x
%res = icmp eq i32 %t1, 0
@@ -108,12 +171,20 @@ define i1 @scalar_i32_signbit_eq(i32 %x, i32 %y) nounwind {
}
define i1 @scalar_i32_lowestbit_eq(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: scalar_i32_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i32_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i32_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: lsr w8, w8, w1
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i32 1, %y
%t1 = and i32 %t0, %x
%res = icmp eq i32 %t1, 0
@@ -121,12 +192,20 @@ define i1 @scalar_i32_lowestbit_eq(i32 %x, i32 %y) nounwind {
}
define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: scalar_i32_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: tst w8, #0xffff00
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i32_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0xffff00
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i32_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #16776960 // =0xffff00
+; CHECK-GI-NEXT: lsr w8, w8, w1
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i32 16776960, %y
%t1 = and i32 %t0, %x
%res = icmp eq i32 %t1, 0
@@ -136,12 +215,20 @@ define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
; i64 scalar
define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: scalar_i64_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl x8, x0, x1
-; CHECK-NEXT: tst x8, #0x8000000000000000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i64_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl x8, x0, x1
+; CHECK-SD-NEXT: tst x8, #0x8000000000000000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i64_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000
+; CHECK-GI-NEXT: lsr x8, x8, x1
+; CHECK-GI-NEXT: tst x8, x0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i64 9223372036854775808, %y
%t1 = and i64 %t0, %x
%res = icmp eq i64 %t1, 0
@@ -149,12 +236,20 @@ define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
}
define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: scalar_i64_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl x8, x0, x1
-; CHECK-NEXT: tst x8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i64_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl x8, x0, x1
+; CHECK-SD-NEXT: tst x8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i64_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: lsr x8, x8, x1
+; CHECK-GI-NEXT: tst x8, x0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i64 1, %y
%t1 = and i64 %t0, %x
%res = icmp eq i64 %t1, 0
@@ -162,12 +257,20 @@ define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
}
define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: scalar_i64_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl x8, x0, x1
-; CHECK-NEXT: tst x8, #0xffffffff0000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i64_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl x8, x0, x1
+; CHECK-SD-NEXT: tst x8, #0xffffffff0000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i64_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #281474976645120 // =0xffffffff0000
+; CHECK-GI-NEXT: lsr x8, x8, x1
+; CHECK-GI-NEXT: tst x8, x0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i64 281474976645120, %y
%t1 = and i64 %t0, %x
%res = icmp eq i64 %t1, 0
@@ -179,14 +282,24 @@ define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
;------------------------------------------------------------------------------;
define <4 x i1> @vec_4xi32_splat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_splat_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v0.16b, v2.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_splat_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: ushl v0.4s, v0.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v0.16b, v2.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_splat_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v2.4s, #1
+; CHECK-GI-NEXT: neg v1.4s, v1.4s
+; CHECK-GI-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = lshr <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
@@ -211,44 +324,86 @@ define <4 x i1> @vec_4xi32_nonsplat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
}
define <4 x i1> @vec_4xi32_nonsplat_undef0_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_nonsplat_undef0_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v0.16b, v2.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_nonsplat_undef0_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: ushl v0.4s, v0.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v0.16b, v2.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_nonsplat_undef0_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: neg v1.4s, v1.4s
+; CHECK-GI-NEXT: fmov s2, w8
+; CHECK-GI-NEXT: mov v2.s[1], w8
+; CHECK-GI-NEXT: mov v2.s[3], w8
+; CHECK-GI-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = lshr <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
ret <4 x i1> %res
}
define <4 x i1> @vec_4xi32_nonsplat_undef1_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_nonsplat_undef1_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: neg v1.4s, v1.4s
-; CHECK-NEXT: ushl v1.4s, v2.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_nonsplat_undef1_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: neg v1.4s, v1.4s
+; CHECK-SD-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_nonsplat_undef1_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi d2, #0000000000000000
+; CHECK-GI-NEXT: movi v3.4s, #1
+; CHECK-GI-NEXT: neg v1.4s, v1.4s
+; CHECK-GI-NEXT: mov v2.s[1], wzr
+; CHECK-GI-NEXT: ushl v1.4s, v3.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: mov v2.s[3], wzr
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v2.4s
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = lshr <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
ret <4 x i1> %res
}
define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_nonsplat_undef2_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: neg v1.4s, v1.4s
-; CHECK-NEXT: ushl v1.4s, v2.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_nonsplat_undef2_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: neg v1.4s, v1.4s
+; CHECK-SD-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_nonsplat_undef2_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: movi d2, #0000000000000000
+; CHECK-GI-NEXT: neg v1.4s, v1.4s
+; CHECK-GI-NEXT: fmov s3, w8
+; CHECK-GI-NEXT: mov v3.s[1], w8
+; CHECK-GI-NEXT: mov v2.s[1], wzr
+; CHECK-GI-NEXT: mov v3.s[3], w8
+; CHECK-GI-NEXT: mov v2.s[3], wzr
+; CHECK-GI-NEXT: ushl v1.4s, v3.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v2.4s
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = lshr <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
@@ -260,11 +415,20 @@ define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwi
;------------------------------------------------------------------------------;
define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_signbit_ne:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsl w8, w0, w1
-; CHECK-NEXT: ubfx w0, w8, #7, #1
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_signbit_ne:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsl w8, w0, w1
+; CHECK-SD-NEXT: ubfx w0, w8, #7, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_signbit_ne:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #128 // =0x80
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, ne
+; CHECK-GI-NEXT: ret
%t0 = lshr i8 128, %y
%t1 = and i8 %t0, %x
%res = icmp ne i8 %t1, 0 ; we are perfectly happy with 'ne' predicate
@@ -315,14 +479,24 @@ define i1 @scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
}
define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_signbit_eq_with_nonzero:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mov w8, #128 // =0x80
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: and w8, w8, w0
-; CHECK-NEXT: cmp w8, #1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_signbit_eq_with_nonzero:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: mov w8, #128 // =0x80
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: and w8, w8, w0
+; CHECK-SD-NEXT: cmp w8, #1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_signbit_eq_with_nonzero:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #128 // =0x80
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsr w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: cmp w8, #1
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = lshr i8 128, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 1 ; should be comparing with 0
diff --git a/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-shl-in-eqcmp-zero.ll b/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
index 4a73b10811d29..cc1bf27b8d4b7 100644
--- a/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/AArch64/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefix=CHECK
+; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-unknown -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
; We are looking for the following pattern here:
; (X & (C << Y)) ==/!= 0
@@ -13,13 +14,23 @@
; i8 scalar
define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: tst w8, #0x80
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: tst w8, #0x80
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xff
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i8 128, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 0
@@ -27,13 +38,23 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
}
define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: tst w8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xff
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i8 1, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 0
@@ -41,13 +62,23 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
}
define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: tst w8, #0x18
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: tst w8, #0x18
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #24 // =0x18
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xff
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i8 24, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 0
@@ -57,13 +88,23 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
; i16 scalar
define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: scalar_i16_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: tst w8, #0x8000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i16_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: tst w8, #0x8000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i16_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-32768 // =0xffff8000
+; CHECK-GI-NEXT: and w9, w1, #0xffff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xffff
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i16 32768, %y
%t1 = and i16 %t0, %x
%res = icmp eq i16 %t1, 0
@@ -71,13 +112,23 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
}
define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: scalar_i16_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i16_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: tst w8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i16_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: and w9, w1, #0xffff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xffff
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i16 1, %y
%t1 = and i16 %t0, %x
%res = icmp eq i16 %t1, 0
@@ -85,13 +136,23 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
}
define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: scalar_i16_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: tst w8, #0xff0
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i16_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: tst w8, #0xff0
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i16_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #4080 // =0xff0
+; CHECK-GI-NEXT: and w9, w1, #0xffff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xffff
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i16 4080, %y
%t1 = and i16 %t0, %x
%res = icmp eq i16 %t1, 0
@@ -101,12 +162,20 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
; i32 scalar
define i1 @scalar_i32_signbit_eq(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: scalar_i32_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsr w8, w0, w1
-; CHECK-NEXT: tst w8, #0x80000000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i32_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsr w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x80000000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i32_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-2147483648 // =0x80000000
+; CHECK-GI-NEXT: lsl w8, w8, w1
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i32 2147483648, %y
%t1 = and i32 %t0, %x
%res = icmp eq i32 %t1, 0
@@ -114,12 +183,20 @@ define i1 @scalar_i32_signbit_eq(i32 %x, i32 %y) nounwind {
}
define i1 @scalar_i32_lowestbit_eq(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: scalar_i32_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsr w8, w0, w1
-; CHECK-NEXT: tst w8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i32_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsr w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i32_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: lsl w8, w8, w1
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i32 1, %y
%t1 = and i32 %t0, %x
%res = icmp eq i32 %t1, 0
@@ -127,12 +204,20 @@ define i1 @scalar_i32_lowestbit_eq(i32 %x, i32 %y) nounwind {
}
define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
-; CHECK-LABEL: scalar_i32_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsr w8, w0, w1
-; CHECK-NEXT: tst w8, #0xffff00
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i32_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsr w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0xffff00
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i32_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #16776960 // =0xffff00
+; CHECK-GI-NEXT: lsl w8, w8, w1
+; CHECK-GI-NEXT: tst w8, w0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i32 16776960, %y
%t1 = and i32 %t0, %x
%res = icmp eq i32 %t1, 0
@@ -142,12 +227,20 @@ define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
; i64 scalar
define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: scalar_i64_signbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsr x8, x0, x1
-; CHECK-NEXT: tst x8, #0x8000000000000000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i64_signbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsr x8, x0, x1
+; CHECK-SD-NEXT: tst x8, #0x8000000000000000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i64_signbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000
+; CHECK-GI-NEXT: lsl x8, x8, x1
+; CHECK-GI-NEXT: tst x8, x0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i64 9223372036854775808, %y
%t1 = and i64 %t0, %x
%res = icmp eq i64 %t1, 0
@@ -155,12 +248,20 @@ define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
}
define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: scalar_i64_lowestbit_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsr x8, x0, x1
-; CHECK-NEXT: tst x8, #0x1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i64_lowestbit_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsr x8, x0, x1
+; CHECK-SD-NEXT: tst x8, #0x1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i64_lowestbit_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: lsl x8, x8, x1
+; CHECK-GI-NEXT: tst x8, x0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i64 1, %y
%t1 = and i64 %t0, %x
%res = icmp eq i64 %t1, 0
@@ -168,12 +269,20 @@ define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
}
define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: scalar_i64_bitsinmiddle_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: lsr x8, x0, x1
-; CHECK-NEXT: tst x8, #0xffffffff0000
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i64_bitsinmiddle_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: lsr x8, x0, x1
+; CHECK-SD-NEXT: tst x8, #0xffffffff0000
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i64_bitsinmiddle_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #281474976645120 // =0xffffffff0000
+; CHECK-GI-NEXT: lsl x8, x8, x1
+; CHECK-GI-NEXT: tst x8, x0
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%t0 = shl i64 281474976645120, %y
%t1 = and i64 %t0, %x
%res = icmp eq i64 %t1, 0
@@ -216,42 +325,81 @@ define <4 x i1> @vec_4xi32_nonsplat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
}
define <4 x i1> @vec_4xi32_nonsplat_undef0_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_nonsplat_undef0_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: ushl v1.4s, v2.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_nonsplat_undef0_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_nonsplat_undef0_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: fmov s2, w8
+; CHECK-GI-NEXT: mov v2.s[1], w8
+; CHECK-GI-NEXT: mov v2.s[3], w8
+; CHECK-GI-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = shl <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
ret <4 x i1> %res
}
define <4 x i1> @vec_4xi32_nonsplat_undef1_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_nonsplat_undef1_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: ushl v1.4s, v2.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_nonsplat_undef1_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_nonsplat_undef1_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi d3, #0000000000000000
+; CHECK-GI-NEXT: movi v2.4s, #1
+; CHECK-GI-NEXT: mov v3.s[1], wzr
+; CHECK-GI-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: mov v3.s[3], wzr
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v3.4s
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = shl <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
ret <4 x i1> %res
}
define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
-; CHECK-LABEL: vec_4xi32_nonsplat_undef2_eq:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v2.4s, #1
-; CHECK-NEXT: ushl v1.4s, v2.4s, v1.4s
-; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
-; CHECK-NEXT: cmeq v0.4s, v0.4s, #0
-; CHECK-NEXT: xtn v0.4h, v0.4s
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: vec_4xi32_nonsplat_undef2_eq:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v2.4s, #1
+; CHECK-SD-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-SD-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-SD-NEXT: cmeq v0.4s, v0.4s, #0
+; CHECK-SD-NEXT: xtn v0.4h, v0.4s
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: vec_4xi32_nonsplat_undef2_eq:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: movi d3, #0000000000000000
+; CHECK-GI-NEXT: fmov s2, w8
+; CHECK-GI-NEXT: mov v2.s[1], w8
+; CHECK-GI-NEXT: mov v3.s[1], wzr
+; CHECK-GI-NEXT: mov v2.s[3], w8
+; CHECK-GI-NEXT: mov v3.s[3], wzr
+; CHECK-GI-NEXT: ushl v1.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b
+; CHECK-GI-NEXT: cmeq v0.4s, v0.4s, v3.4s
+; CHECK-GI-NEXT: xtn v0.4h, v0.4s
+; CHECK-GI-NEXT: ret
%t0 = shl <4 x i32> , %y
%t1 = and <4 x i32> %t0, %x
%res = icmp eq <4 x i32> %t1,
@@ -263,12 +411,22 @@ define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwi
;------------------------------------------------------------------------------;
define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_signbit_ne:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xff
-; CHECK-NEXT: lsr w8, w8, w1
-; CHECK-NEXT: lsr w0, w8, #7
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_signbit_ne:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xff
+; CHECK-SD-NEXT: lsr w8, w8, w1
+; CHECK-SD-NEXT: lsr w0, w8, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_signbit_ne:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: tst w8, #0xff
+; CHECK-GI-NEXT: cset w0, ne
+; CHECK-GI-NEXT: ret
%t0 = shl i8 128, %y
%t1 = and i8 %t0, %x
%res = icmp ne i8 %t1, 0 ; we are perfectly happy with 'ne' predicate
@@ -310,13 +468,24 @@ define i1 @scalar_i32_x_is_const2_eq(i32 %y) nounwind {
}
define i1 @scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_bitsinmiddle_slt:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mov w8, #24 // =0x18
-; CHECK-NEXT: lsl w8, w8, w1
-; CHECK-NEXT: and w8, w8, w0
-; CHECK-NEXT: ubfx w0, w8, #7, #1
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_bitsinmiddle_slt:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: mov w8, #24 // =0x18
+; CHECK-SD-NEXT: lsl w8, w8, w1
+; CHECK-SD-NEXT: and w8, w8, w0
+; CHECK-SD-NEXT: ubfx w0, w8, #7, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_bitsinmiddle_slt:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #24 // =0x18
+; CHECK-GI-NEXT: and w9, w1, #0xff
+; CHECK-GI-NEXT: lsl w8, w8, w9
+; CHECK-GI-NEXT: and w8, w8, w0
+; CHECK-GI-NEXT: sxtb w8, w8
+; CHECK-GI-NEXT: cmp w8, #0
+; CHECK-GI-NEXT: cset w0, mi
+; CHECK-GI-NEXT: ret
%t0 = shl i8 24, %y
%t1 = and i8 %t0, %x
%res = icmp slt i8 %t1, 0
@@ -324,15 +493,20 @@ define i1 @scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
}
define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
-; CHECK-LABEL: scalar_i8_signbit_eq_with_nonzero:
-; CHECK: // %bb.0:
-; CHECK-NEXT: mov w8, #-128 // =0xffffff80
-; CHECK-NEXT: lsl w8, w8, w1
-; CHECK-NEXT: and w8, w8, w0
-; CHECK-NEXT: and w8, w8, #0x80
-; CHECK-NEXT: cmp w8, #1
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: scalar_i8_signbit_eq_with_nonzero:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-SD-NEXT: lsl w8, w8, w1
+; CHECK-SD-NEXT: and w8, w8, w0
+; CHECK-SD-NEXT: and w8, w8, #0x80
+; CHECK-SD-NEXT: cmp w8, #1
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: scalar_i8_signbit_eq_with_nonzero:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w0, wzr
+; CHECK-GI-NEXT: ret
%t0 = shl i8 128, %y
%t1 = and i8 %t0, %x
%res = icmp eq i8 %t1, 1 ; should be comparing with 0
diff --git a/llvm/test/CodeGen/AArch64/signbit-test.ll b/llvm/test/CodeGen/AArch64/signbit-test.ll
index c74a934ee09d8..298495bcf5a01 100644
--- a/llvm/test/CodeGen/AArch64/signbit-test.ll
+++ b/llvm/test/CodeGen/AArch64/signbit-test.ll
@@ -1,13 +1,21 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s
+; RUN: llc -mtriple=aarch64-- < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-- -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i64 @test_clear_mask_i64_i32(i64 %x) nounwind {
-; CHECK-LABEL: test_clear_mask_i64_i32:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov w8, #42 // =0x2a
-; CHECK-NEXT: cmn w0, #1
-; CHECK-NEXT: csel x0, x8, x0, gt
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_clear_mask_i64_i32:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: mov w8, #42 // =0x2a
+; CHECK-SD-NEXT: cmn w0, #1
+; CHECK-SD-NEXT: csel x0, x8, x0, gt
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_clear_mask_i64_i32:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov w8, #42 // =0x2a
+; CHECK-GI-NEXT: tst x0, #0x80000000
+; CHECK-GI-NEXT: csel x0, x8, x0, eq
+; CHECK-GI-NEXT: ret
entry:
%a = and i64 %x, 2147483648
%r = icmp eq i64 %a, 0
diff --git a/llvm/test/CodeGen/AArch64/signed-truncation-check.ll b/llvm/test/CodeGen/AArch64/signed-truncation-check.ll
index 7c80f9320faec..fc01c6b2c5471 100644
--- a/llvm/test/CodeGen/AArch64/signed-truncation-check.ll
+++ b/llvm/test/CodeGen/AArch64/signed-truncation-check.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
; https://bugs.llvm.org/show_bug.cgi?id=38149
@@ -19,13 +20,22 @@
; ---------------------------------------------------------------------------- ;
define i1 @shifts_eqcmp_i16_i8(i16 %x) nounwind {
-; CHECK-LABEL: shifts_eqcmp_i16_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sxtb w8, w0
-; CHECK-NEXT: and w8, w8, #0xffff
-; CHECK-NEXT: cmp w8, w0, uxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: shifts_eqcmp_i16_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sxtb w8, w0
+; CHECK-SD-NEXT: and w8, w8, #0xffff
+; CHECK-SD-NEXT: cmp w8, w0, uxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: shifts_eqcmp_i16_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: lsl w8, w0, #8
+; CHECK-GI-NEXT: sbfx w8, w8, #8, #8
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, w0, uxth
+; CHECK-GI-NEXT: cset w0, eq
+; CHECK-GI-NEXT: ret
%tmp0 = shl i16 %x, 8 ; 16-8
%tmp1 = ashr exact i16 %tmp0, 8 ; 16-8
%tmp2 = icmp eq i16 %tmp1, %x
@@ -97,26 +107,43 @@ define i1 @shifts_eqcmp_i64_i8(i64 %x) nounwind {
; ---------------------------------------------------------------------------- ;
define i1 @add_ugecmp_i16_i8(i16 %x) nounwind {
-; CHECK-LABEL: add_ugecmp_i16_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: sub w8, w8, #128
-; CHECK-NEXT: lsr w8, w8, #8
-; CHECK-NEXT: cmp w8, #254
-; CHECK-NEXT: cset w0, hi
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i16_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: sub w8, w8, #128
+; CHECK-SD-NEXT: lsr w8, w8, #8
+; CHECK-SD-NEXT: cmp w8, #254
+; CHECK-SD-NEXT: cset w0, hi
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i16_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-GI-NEXT: mov w9, #65280 // =0xff00
+; CHECK-GI-NEXT: add w8, w8, w0, uxth
+; CHECK-GI-NEXT: cmp w8, w9
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, -128 ; ~0U << (8-1)
%tmp1 = icmp uge i16 %tmp0, -256 ; ~0U << 8
ret i1 %tmp1
}
define i1 @add_ugecmp_i32_i16_i8(i16 %xx) nounwind {
-; CHECK-LABEL: add_ugecmp_i32_i16_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: cmp w8, w8, sxtb
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i32_i16_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: cmp w8, w8, sxtb
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i32_i16_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-GI-NEXT: add w8, w8, w0, uxth
+; CHECK-GI-NEXT: cmn w8, #256
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%x = zext i16 %xx to i32
%tmp0 = add i32 %x, -128 ; ~0U << (8-1)
%tmp1 = icmp uge i32 %tmp0, -256 ; ~0U << 8
@@ -124,55 +151,92 @@ define i1 @add_ugecmp_i32_i16_i8(i16 %xx) nounwind {
}
define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {
-; CHECK-LABEL: add_ugecmp_i32_i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp w0, w0, sxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i32_i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp w0, w0, sxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i32_i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: sub w8, w0, #8, lsl #12 // =32768
+; CHECK-GI-NEXT: cmn w8, #16, lsl #12 // =65536
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%tmp0 = add i32 %x, -32768 ; ~0U << (16-1)
%tmp1 = icmp uge i32 %tmp0, -65536 ; ~0U << 16
ret i1 %tmp1
}
define i1 @add_ugecmp_i32_i8(i32 %x) nounwind {
-; CHECK-LABEL: add_ugecmp_i32_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp w0, w0, sxtb
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i32_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp w0, w0, sxtb
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i32_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: sub w8, w0, #128
+; CHECK-GI-NEXT: cmn w8, #256
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%tmp0 = add i32 %x, -128 ; ~0U << (8-1)
%tmp1 = icmp uge i32 %tmp0, -256 ; ~0U << 8
ret i1 %tmp1
}
define i1 @add_ugecmp_i64_i32(i64 %x) nounwind {
-; CHECK-LABEL: add_ugecmp_i64_i32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp x0, w0, sxtw
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i64_i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp x0, w0, sxtw
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i64_i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #-2147483648 // =0xffffffff80000000
+; CHECK-GI-NEXT: mov x9, #-4294967296 // =0xffffffff00000000
+; CHECK-GI-NEXT: add x8, x0, x8
+; CHECK-GI-NEXT: cmp x8, x9
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1)
%tmp1 = icmp uge i64 %tmp0, -4294967296 ; ~0U << 32
ret i1 %tmp1
}
define i1 @add_ugecmp_i64_i16(i64 %x) nounwind {
-; CHECK-LABEL: add_ugecmp_i64_i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp x0, w0, sxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i64_i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp x0, w0, sxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i64_i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: sub x8, x0, #8, lsl #12 // =32768
+; CHECK-GI-NEXT: cmn x8, #16, lsl #12 // =65536
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%tmp0 = add i64 %x, -32768 ; ~0U << (16-1)
%tmp1 = icmp uge i64 %tmp0, -65536 ; ~0U << 16
ret i1 %tmp1
}
define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {
-; CHECK-LABEL: add_ugecmp_i64_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp x0, w0, sxtb
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugecmp_i64_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp x0, w0, sxtb
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugecmp_i64_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: sub x8, x0, #128
+; CHECK-GI-NEXT: cmn x8, #256
+; CHECK-GI-NEXT: cset w0, hs
+; CHECK-GI-NEXT: ret
%tmp0 = add i64 %x, -128 ; ~0U << (8-1)
%tmp1 = icmp uge i64 %tmp0, -256 ; ~0U << 8
ret i1 %tmp1
@@ -180,14 +244,23 @@ define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {
; Slightly more canonical variant
define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {
-; CHECK-LABEL: add_ugtcmp_i16_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: sub w8, w8, #128
-; CHECK-NEXT: lsr w8, w8, #8
-; CHECK-NEXT: cmp w8, #254
-; CHECK-NEXT: cset w0, hi
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ugtcmp_i16_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: sub w8, w8, #128
+; CHECK-SD-NEXT: lsr w8, w8, #8
+; CHECK-SD-NEXT: cmp w8, #254
+; CHECK-SD-NEXT: cset w0, hi
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ugtcmp_i16_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-GI-NEXT: mov w9, #65279 // =0xfeff
+; CHECK-GI-NEXT: add w8, w8, w0, uxth
+; CHECK-GI-NEXT: cmp w8, w9
+; CHECK-GI-NEXT: cset w0, hi
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, -128 ; ~0U << (8-1)
%tmp1 = icmp ugt i16 %tmp0, -257 ; ~0U << 8 - 1
ret i1 %tmp1
@@ -198,68 +271,113 @@ define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {
; ---------------------------------------------------------------------------- ;
define i1 @add_ultcmp_i16_i8(i16 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_i16_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sxtb w8, w0
-; CHECK-NEXT: and w8, w8, #0xffff
-; CHECK-NEXT: cmp w8, w0, uxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_i16_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sxtb w8, w0
+; CHECK-SD-NEXT: and w8, w8, #0xffff
+; CHECK-SD-NEXT: cmp w8, w0, uxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_i16_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #128
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, 128 ; 1U << (8-1)
%tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
}
define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_i32_i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp w0, w0, sxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_i32_i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp w0, w0, sxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_i32_i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #8, lsl #12 // =32768
+; CHECK-GI-NEXT: cmp w8, #16, lsl #12 // =65536
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i32 %x, 32768 ; 1U << (16-1)
%tmp1 = icmp ult i32 %tmp0, 65536 ; 1U << 16
ret i1 %tmp1
}
define i1 @add_ultcmp_i32_i8(i32 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_i32_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp w0, w0, sxtb
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_i32_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp w0, w0, sxtb
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_i32_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #128
+; CHECK-GI-NEXT: cmp w8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i32 %x, 128 ; 1U << (8-1)
%tmp1 = icmp ult i32 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
}
define i1 @add_ultcmp_i64_i32(i64 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_i64_i32:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp x0, w0, sxtw
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_i64_i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp x0, w0, sxtw
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_i64_i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #-2147483648 // =0x80000000
+; CHECK-GI-NEXT: mov x9, #4294967296 // =0x100000000
+; CHECK-GI-NEXT: add x8, x0, x8
+; CHECK-GI-NEXT: cmp x8, x9
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i64 %x, 2147483648 ; 1U << (32-1)
%tmp1 = icmp ult i64 %tmp0, 4294967296 ; 1U << 32
ret i1 %tmp1
}
define i1 @add_ultcmp_i64_i16(i64 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_i64_i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp x0, w0, sxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_i64_i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp x0, w0, sxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_i64_i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add x8, x0, #8, lsl #12 // =32768
+; CHECK-GI-NEXT: cmp x8, #16, lsl #12 // =65536
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i64 %x, 32768 ; 1U << (16-1)
%tmp1 = icmp ult i64 %tmp0, 65536 ; 1U << 16
ret i1 %tmp1
}
define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_i64_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: cmp x0, w0, sxtb
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_i64_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: cmp x0, w0, sxtb
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_i64_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add x8, x0, #128
+; CHECK-GI-NEXT: cmp x8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i64 %x, 128 ; 1U << (8-1)
%tmp1 = icmp ult i64 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
@@ -267,13 +385,21 @@ define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {
; Slightly more canonical variant
define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {
-; CHECK-LABEL: add_ulecmp_i16_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: sxtb w8, w0
-; CHECK-NEXT: and w8, w8, #0xffff
-; CHECK-NEXT: cmp w8, w0, uxth
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ulecmp_i16_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: sxtb w8, w0
+; CHECK-SD-NEXT: and w8, w8, #0xffff
+; CHECK-SD-NEXT: cmp w8, w0, uxth
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ulecmp_i16_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #128
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, #255
+; CHECK-GI-NEXT: cset w0, ls
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, 128 ; 1U << (8-1)
%tmp1 = icmp ule i16 %tmp0, 255 ; (1U << 8) - 1
ret i1 %tmp1
@@ -284,12 +410,20 @@ define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {
; Adding not a constant
define i1 @add_ultcmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind {
-; CHECK-LABEL: add_ultcmp_bad_i16_i8_add:
-; CHECK: // %bb.0:
-; CHECK-NEXT: add w8, w0, w1
-; CHECK-NEXT: tst w8, #0xff00
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_bad_i16_i8_add:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: add w8, w0, w1
+; CHECK-SD-NEXT: tst w8, #0xff00
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_bad_i16_i8_add:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, w1
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, %y
%tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
@@ -311,12 +445,20 @@ define i1 @add_ultcmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind {
; Second constant is not larger than the first one
define i1 @add_ultcmp_bad_i8_i16(i16 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_bad_i8_i16:
-; CHECK: // %bb.0:
-; CHECK-NEXT: and w8, w0, #0xffff
-; CHECK-NEXT: add w8, w8, #128
-; CHECK-NEXT: lsr w0, w8, #16
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_bad_i8_i16:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: and w8, w0, #0xffff
+; CHECK-SD-NEXT: add w8, w8, #128
+; CHECK-SD-NEXT: lsr w0, w8, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_bad_i8_i16:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: and w8, w0, #0xffff
+; CHECK-GI-NEXT: add w8, w8, #128
+; CHECK-GI-NEXT: cmp w8, w8, uxth
+; CHECK-GI-NEXT: cset w0, ne
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, 128 ; 1U << (8-1)
%tmp1 = icmp ult i16 %tmp0, 128 ; 1U << (8-1)
ret i1 %tmp1
@@ -324,12 +466,20 @@ define i1 @add_ultcmp_bad_i8_i16(i16 %x) nounwind {
; First constant is not power of two
define i1 @add_ultcmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
-; CHECK: // %bb.0:
-; CHECK-NEXT: add w8, w0, #192
-; CHECK-NEXT: tst w8, #0xff00
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: add w8, w0, #192
+; CHECK-SD-NEXT: tst w8, #0xff00
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #192
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1))
%tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
@@ -351,12 +501,20 @@ define i1 @add_ultcmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind {
; Magic check fails, 64 << 1 != 256
define i1 @add_ultcmp_bad_i16_i8_magic(i16 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_bad_i16_i8_magic:
-; CHECK: // %bb.0:
-; CHECK-NEXT: add w8, w0, #64
-; CHECK-NEXT: tst w8, #0xff00
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_bad_i16_i8_magic:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: add w8, w0, #64
+; CHECK-SD-NEXT: tst w8, #0xff00
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_bad_i16_i8_magic:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #64
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, 64 ; 1U << (8-1-1)
%tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
@@ -364,12 +522,20 @@ define i1 @add_ultcmp_bad_i16_i8_magic(i16 %x) nounwind {
; Bad 'destination type'
define i1 @add_ultcmp_bad_i16_i4(i16 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_bad_i16_i4:
-; CHECK: // %bb.0:
-; CHECK-NEXT: add w8, w0, #8
-; CHECK-NEXT: tst w8, #0xfff0
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_bad_i16_i4:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: add w8, w0, #8
+; CHECK-SD-NEXT: tst w8, #0xfff0
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_bad_i16_i4:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #8
+; CHECK-GI-NEXT: and w8, w8, #0xffff
+; CHECK-GI-NEXT: cmp w8, #16
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i16 %x, 8 ; 1U << (4-1)
%tmp1 = icmp ult i16 %tmp0, 16 ; 1U << 4
ret i1 %tmp1
@@ -377,12 +543,20 @@ define i1 @add_ultcmp_bad_i16_i4(i16 %x) nounwind {
; Bad storage type
define i1 @add_ultcmp_bad_i24_i8(i24 %x) nounwind {
-; CHECK-LABEL: add_ultcmp_bad_i24_i8:
-; CHECK: // %bb.0:
-; CHECK-NEXT: add w8, w0, #128
-; CHECK-NEXT: tst w8, #0xffff00
-; CHECK-NEXT: cset w0, eq
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: add_ultcmp_bad_i24_i8:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: add w8, w0, #128
+; CHECK-SD-NEXT: tst w8, #0xffff00
+; CHECK-SD-NEXT: cset w0, eq
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: add_ultcmp_bad_i24_i8:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: add w8, w0, #128
+; CHECK-GI-NEXT: and w8, w8, #0xffffff
+; CHECK-GI-NEXT: cmp w8, #256
+; CHECK-GI-NEXT: cset w0, lo
+; CHECK-GI-NEXT: ret
%tmp0 = add i24 %x, 128 ; 1U << (8-1)
%tmp1 = icmp ult i24 %tmp0, 256 ; 1U << 8
ret i1 %tmp1
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
index 7714c032d1737..d3e211855d7ed 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
@@ -113,9 +113,9 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_ne_zero_non_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_ne_zero_non_compare:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s0, 0, s0
-; CHECK-NEXT: s_cmp_eq_u32 s0, 0
+; CHECK-NEXT: s_xor_b32 s0, s0, 1
+; CHECK-NEXT: s_and_b32 s0, s0, 1
+; CHECK-NEXT: s_cmp_lg_u32 s0, 0
; CHECK-NEXT: s_cbranch_scc1 .LBB8_2
; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
@@ -161,16 +161,17 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_eq_zero_non_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_eq_zero_non_compare:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s0, 0, s0
+; CHECK-NEXT: s_xor_b32 s0, s0, 1
+; CHECK-NEXT: s_xor_b32 s0, s0, 1
+; CHECK-NEXT: s_and_b32 s0, s0, 1
; CHECK-NEXT: s_cmp_lg_u32 s0, 0
-; CHECK-NEXT: s_cbranch_scc0 .LBB10_2
-; CHECK-NEXT: ; %bb.1: ; %false
-; CHECK-NEXT: s_mov_b32 s0, 33
-; CHECK-NEXT: s_branch .LBB10_3
-; CHECK-NEXT: .LBB10_2: ; %true
+; CHECK-NEXT: s_cbranch_scc1 .LBB10_2
+; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
; CHECK-NEXT: s_branch .LBB10_3
+; CHECK-NEXT: .LBB10_2: ; %false
+; CHECK-NEXT: s_mov_b32 s0, 33
+; CHECK-NEXT: s_branch .LBB10_3
; CHECK-NEXT: .LBB10_3:
%c = trunc i32 %v to i1
%ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %c)
@@ -208,11 +209,7 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_ne_zero_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_ne_zero_compare:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_cmp_lt_u32 s0, 12
-; CHECK-NEXT: s_cselect_b32 s0, 1, 0
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s0, 0, s0
-; CHECK-NEXT: s_cmp_eq_u32 s0, 0
+; CHECK-NEXT: s_cmp_ge_u32 s0, 12
; CHECK-NEXT: s_cbranch_scc1 .LBB12_2
; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
@@ -258,17 +255,13 @@ define amdgpu_cs i32 @branch_uniform_ballot_eq_zero_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_eq_zero_compare:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_cmp_lt_u32 s0, 12
-; CHECK-NEXT: s_cselect_b32 s0, 1, 0
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s0, 0, s0
-; CHECK-NEXT: s_cmp_lg_u32 s0, 0
-; CHECK-NEXT: s_cbranch_scc0 .LBB14_2
-; CHECK-NEXT: ; %bb.1: ; %false
-; CHECK-NEXT: s_mov_b32 s0, 33
-; CHECK-NEXT: s_branch .LBB14_3
-; CHECK-NEXT: .LBB14_2: ; %true
+; CHECK-NEXT: s_cbranch_scc1 .LBB14_2
+; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
; CHECK-NEXT: s_branch .LBB14_3
+; CHECK-NEXT: .LBB14_2: ; %false
+; CHECK-NEXT: s_mov_b32 s0, 33
+; CHECK-NEXT: s_branch .LBB14_3
; CHECK-NEXT: .LBB14_3:
%c = icmp ult i32 %v, 12
%ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %c)
@@ -310,14 +303,12 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_ne_zero_and(i32 inreg %v1, i32 inreg %v2) {
; CHECK-LABEL: branch_uniform_ballot_ne_zero_and:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_cmp_lt_u32 s0, 12
+; CHECK-NEXT: s_cmp_ge_u32 s0, 12
; CHECK-NEXT: s_cselect_b32 s0, 1, 0
-; CHECK-NEXT: s_cmp_gt_u32 s1, 34
+; CHECK-NEXT: s_cmp_le_u32 s1, 34
; CHECK-NEXT: s_cselect_b32 s1, 1, 0
-; CHECK-NEXT: s_and_b32 s0, s0, s1
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s0, 0, s0
-; CHECK-NEXT: s_cmp_eq_u32 s0, 0
+; CHECK-NEXT: s_or_b32 s0, s0, s1
+; CHECK-NEXT: s_cmp_lg_u32 s0, 0
; CHECK-NEXT: s_cbranch_scc1 .LBB16_2
; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
@@ -372,16 +363,14 @@ define amdgpu_cs i32 @branch_uniform_ballot_eq_zero_and(i32 inreg %v1, i32 inreg
; CHECK-NEXT: s_cmp_gt_u32 s1, 34
; CHECK-NEXT: s_cselect_b32 s1, 1, 0
; CHECK-NEXT: s_and_b32 s0, s0, s1
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s0, 0, s0
; CHECK-NEXT: s_cmp_lg_u32 s0, 0
-; CHECK-NEXT: s_cbranch_scc0 .LBB18_2
-; CHECK-NEXT: ; %bb.1: ; %false
-; CHECK-NEXT: s_mov_b32 s0, 33
-; CHECK-NEXT: s_branch .LBB18_3
-; CHECK-NEXT: .LBB18_2: ; %true
+; CHECK-NEXT: s_cbranch_scc1 .LBB18_2
+; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
; CHECK-NEXT: s_branch .LBB18_3
+; CHECK-NEXT: .LBB18_2: ; %false
+; CHECK-NEXT: s_mov_b32 s0, 33
+; CHECK-NEXT: s_branch .LBB18_3
; CHECK-NEXT: .LBB18_3:
%v1c = icmp ult i32 %v1, 12
%v2c = icmp ugt i32 %v2, 34
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
index 7b8166948610b..250fbc7c0f147 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
@@ -116,9 +116,9 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_ne_zero_non_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_ne_zero_non_compare:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 0, s0
-; CHECK-NEXT: s_cmp_eq_u64 s[0:1], 0
+; CHECK-NEXT: s_xor_b32 s0, s0, 1
+; CHECK-NEXT: s_and_b32 s0, s0, 1
+; CHECK-NEXT: s_cmp_lg_u32 s0, 0
; CHECK-NEXT: s_cbranch_scc1 .LBB8_2
; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
@@ -164,16 +164,17 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_eq_zero_non_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_eq_zero_non_compare:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 0, s0
-; CHECK-NEXT: s_cmp_lg_u64 s[0:1], 0
-; CHECK-NEXT: s_cbranch_scc0 .LBB10_2
-; CHECK-NEXT: ; %bb.1: ; %false
-; CHECK-NEXT: s_mov_b32 s0, 33
-; CHECK-NEXT: s_branch .LBB10_3
-; CHECK-NEXT: .LBB10_2: ; %true
+; CHECK-NEXT: s_xor_b32 s0, s0, 1
+; CHECK-NEXT: s_xor_b32 s0, s0, 1
+; CHECK-NEXT: s_and_b32 s0, s0, 1
+; CHECK-NEXT: s_cmp_lg_u32 s0, 0
+; CHECK-NEXT: s_cbranch_scc1 .LBB10_2
+; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
; CHECK-NEXT: s_branch .LBB10_3
+; CHECK-NEXT: .LBB10_2: ; %false
+; CHECK-NEXT: s_mov_b32 s0, 33
+; CHECK-NEXT: s_branch .LBB10_3
; CHECK-NEXT: .LBB10_3:
%c = trunc i32 %v to i1
%ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %c)
@@ -211,11 +212,7 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_ne_zero_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_ne_zero_compare:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_cmp_lt_u32 s0, 12
-; CHECK-NEXT: s_cselect_b32 s0, 1, 0
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 0, s0
-; CHECK-NEXT: s_cmp_eq_u64 s[0:1], 0
+; CHECK-NEXT: s_cmp_ge_u32 s0, 12
; CHECK-NEXT: s_cbranch_scc1 .LBB12_2
; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
@@ -261,17 +258,13 @@ define amdgpu_cs i32 @branch_uniform_ballot_eq_zero_compare(i32 inreg %v) {
; CHECK-LABEL: branch_uniform_ballot_eq_zero_compare:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_cmp_lt_u32 s0, 12
-; CHECK-NEXT: s_cselect_b32 s0, 1, 0
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 0, s0
-; CHECK-NEXT: s_cmp_lg_u64 s[0:1], 0
-; CHECK-NEXT: s_cbranch_scc0 .LBB14_2
-; CHECK-NEXT: ; %bb.1: ; %false
-; CHECK-NEXT: s_mov_b32 s0, 33
-; CHECK-NEXT: s_branch .LBB14_3
-; CHECK-NEXT: .LBB14_2: ; %true
+; CHECK-NEXT: s_cbranch_scc1 .LBB14_2
+; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
; CHECK-NEXT: s_branch .LBB14_3
+; CHECK-NEXT: .LBB14_2: ; %false
+; CHECK-NEXT: s_mov_b32 s0, 33
+; CHECK-NEXT: s_branch .LBB14_3
; CHECK-NEXT: .LBB14_3:
%c = icmp ult i32 %v, 12
%ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %c)
@@ -313,14 +306,12 @@ false:
define amdgpu_cs i32 @branch_uniform_ballot_ne_zero_and(i32 inreg %v1, i32 inreg %v2) {
; CHECK-LABEL: branch_uniform_ballot_ne_zero_and:
; CHECK: ; %bb.0:
-; CHECK-NEXT: s_cmp_lt_u32 s0, 12
+; CHECK-NEXT: s_cmp_ge_u32 s0, 12
; CHECK-NEXT: s_cselect_b32 s0, 1, 0
-; CHECK-NEXT: s_cmp_gt_u32 s1, 34
+; CHECK-NEXT: s_cmp_le_u32 s1, 34
; CHECK-NEXT: s_cselect_b32 s1, 1, 0
-; CHECK-NEXT: s_and_b32 s0, s0, s1
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 0, s0
-; CHECK-NEXT: s_cmp_eq_u64 s[0:1], 0
+; CHECK-NEXT: s_or_b32 s0, s0, s1
+; CHECK-NEXT: s_cmp_lg_u32 s0, 0
; CHECK-NEXT: s_cbranch_scc1 .LBB16_2
; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
@@ -375,16 +366,14 @@ define amdgpu_cs i32 @branch_uniform_ballot_eq_zero_and(i32 inreg %v1, i32 inreg
; CHECK-NEXT: s_cmp_gt_u32 s1, 34
; CHECK-NEXT: s_cselect_b32 s1, 1, 0
; CHECK-NEXT: s_and_b32 s0, s0, s1
-; CHECK-NEXT: s_and_b32 s0, 1, s0
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 0, s0
-; CHECK-NEXT: s_cmp_lg_u64 s[0:1], 0
-; CHECK-NEXT: s_cbranch_scc0 .LBB18_2
-; CHECK-NEXT: ; %bb.1: ; %false
-; CHECK-NEXT: s_mov_b32 s0, 33
-; CHECK-NEXT: s_branch .LBB18_3
-; CHECK-NEXT: .LBB18_2: ; %true
+; CHECK-NEXT: s_cmp_lg_u32 s0, 0
+; CHECK-NEXT: s_cbranch_scc1 .LBB18_2
+; CHECK-NEXT: ; %bb.1: ; %true
; CHECK-NEXT: s_mov_b32 s0, 42
; CHECK-NEXT: s_branch .LBB18_3
+; CHECK-NEXT: .LBB18_2: ; %false
+; CHECK-NEXT: s_mov_b32 s0, 33
+; CHECK-NEXT: s_branch .LBB18_3
; CHECK-NEXT: .LBB18_3:
%v1c = icmp ult i32 %v1, 12
%v2c = icmp ugt i32 %v2, 34
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-miscellaneous-uniform-intrinsic.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-miscellaneous-uniform-intrinsic.ll
new file mode 100644
index 0000000000000..34d4c519851d4
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-miscellaneous-uniform-intrinsic.ll
@@ -0,0 +1,173 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -o - %s | FileCheck %s
+define amdgpu_kernel void @readfirstlane_with_readfirstlane(ptr addrspace(1) %out) {
+; CHECK-LABEL: readfirstlane_with_readfirstlane:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, 5
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %v1 = call i32 @llvm.amdgcn.readfirstlane(i32 5)
+ %v2 = call i32 @llvm.amdgcn.readfirstlane(i32 %v1)
+ store i32 %v2, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @readfirstlane_with_readlane(ptr addrspace(1) %out) {
+; CHECK-LABEL: readfirstlane_with_readlane:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_bfe_u32 v1, v0, 10, 10
+; CHECK-NEXT: v_and_b32_e32 v0, 0x3ff, v0
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT: v_readfirstlane_b32 s2, v1
+; CHECK-NEXT: v_readlane_b32 s2, v0, s2
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; CHECK-NEXT: v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s2
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %tidx = call i32 @llvm.amdgcn.workitem.id.x()
+ %tidy = call i32 @llvm.amdgcn.workitem.id.y()
+ %v1 = call i32 @llvm.amdgcn.readlane(i32 %tidx, i32 %tidy)
+ %v2 = call i32 @llvm.amdgcn.readfirstlane(i32 %v1)
+ store i32 %v2, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @readlane_with_firstlane(ptr addrspace(1) %out) {
+; CHECK-LABEL: readlane_with_firstlane:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_and_b32_e32 v0, 0x3ff, v0
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT: v_readfirstlane_b32 s2, v0
+; CHECK-NEXT: v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s2
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %tidx = call i32 @llvm.amdgcn.workitem.id.x()
+ %v1 = call i32 @llvm.amdgcn.readfirstlane(i32 %tidx)
+ %v2 = call i32 @llvm.amdgcn.readlane(i32 %v1, i32 3)
+ store i32 %v2, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @readlane_readlane(ptr addrspace(1) %out) {
+; CHECK-LABEL: readlane_readlane:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_bfe_u32 v1, v0, 10, 10
+; CHECK-NEXT: v_and_b32_e32 v0, 0x3ff, v0
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT: v_readfirstlane_b32 s2, v1
+; CHECK-NEXT: v_readlane_b32 s2, v0, s2
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; CHECK-NEXT: v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s2
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %tidx = call i32 @llvm.amdgcn.workitem.id.x()
+ %tidy = call i32 @llvm.amdgcn.workitem.id.y()
+ %v1 = call i32 @llvm.amdgcn.readlane(i32 %tidx, i32 %tidy)
+ %v2 = call i32 @llvm.amdgcn.readlane(i32 %v1, i32 2)
+ store i32 %v2, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @permlane64_uniform(ptr addrspace(1) %out, i32 %src) {
+; CHECK-LABEL: permlane64_uniform:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_clause 0x1
+; CHECK-NEXT: s_load_b32 s2, s[4:5], 0x8
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s2
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %v = call i32 @llvm.amdgcn.permlane64(i32 %src)
+ store i32 %v, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @permlane64_nonuniform(i32 addrspace(1)* %out) {
+; CHECK-LABEL: permlane64_nonuniform:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_and_b32_e32 v0, 0x3ff, v0
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; CHECK-NEXT: v_permlane64_b32 v1, v0
+; CHECK-NEXT: v_lshlrev_b32_e32 v0, 2, v0
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %tid = call i32 @llvm.amdgcn.workitem.id.x()
+ %v = call i32 @llvm.amdgcn.permlane64(i32 %tid)
+ %out_ptr = getelementptr i32, i32 addrspace(1)* %out, i32 %tid
+ store i32 %v, i32 addrspace(1)* %out_ptr
+ ret void
+}
+
+define amdgpu_kernel void @permlane64_nonuniform_expression(i32 addrspace(1)* %out) {
+; CHECK-LABEL: permlane64_nonuniform_expression:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_and_b32_e32 v0, 0x3ff, v0
+; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT: v_add_nc_u32_e32 v1, 1, v0
+; CHECK-NEXT: v_lshlrev_b32_e32 v0, 2, v0
+; CHECK-NEXT: v_permlane64_b32 v1, v1
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_endpgm
+ %tid = call i32 @llvm.amdgcn.workitem.id.x()
+ %tid2 = add i32 %tid, 1
+ %v = call i32 @llvm.amdgcn.permlane64(i32 %tid2)
+ %out_ptr = getelementptr i32, i32 addrspace(1)* %out, i32 %tid
+ store i32 %v, i32 addrspace(1)* %out_ptr
+ ret void
+}
+
+define protected amdgpu_kernel void @trivial_waterfall_eq_zero(ptr addrspace(1) %out) {
+; CHECK-LABEL: trivial_waterfall_eq_zero:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: s_load_b64 s[0:1], s[4:5], 0x0
+; CHECK-NEXT: v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, 5
+; CHECK-NEXT: s_mov_b32 s2, 0
+; CHECK-NEXT: s_branch .LBB7_2
+; CHECK-NEXT: .LBB7_1: ; %Flow
+; CHECK-NEXT: ; in Loop: Header=BB7_2 Depth=1
+; CHECK-NEXT: s_and_not1_b32 vcc_lo, exec_lo, s2
+; CHECK-NEXT: s_mov_b32 s2, -1
+; CHECK-NEXT: s_cbranch_vccz .LBB7_4
+; CHECK-NEXT: .LBB7_2: ; %while
+; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: s_and_b32 vcc_lo, exec_lo, s2
+; CHECK-NEXT: s_mov_b32 s2, -1
+; CHECK-NEXT: s_cbranch_vccnz .LBB7_1
+; CHECK-NEXT: ; %bb.3: ; %if
+; CHECK-NEXT: ; in Loop: Header=BB7_2 Depth=1
+; CHECK-NEXT: s_mov_b32 s2, 0
+; CHECK-NEXT: s_waitcnt lgkmcnt(0)
+; CHECK-NEXT: global_store_b32 v0, v1, s[0:1]
+; CHECK-NEXT: s_branch .LBB7_1
+; CHECK-NEXT: .LBB7_4: ; %exit
+; CHECK-NEXT: s_endpgm
+entry:
+ br label %while
+
+while:
+ %done = phi i1 [ 0, %entry ], [ 1, %if ]
+ %not_done = xor i1 %done, true
+ %ballot = tail call i64 @llvm.amdgcn.ballot.i64(i1 %not_done)
+ %is_done = icmp eq i64 %ballot, 0 ; in this case is_done = !not_done
+ br i1 %is_done, label %exit, label %if
+
+if:
+ store i32 5, ptr addrspace(1) %out
+ br label %while
+
+exit:
+ ret void
+}
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-uniform-waterfall.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-uniform-waterfall.ll
index 33ce278028bba..c962c05d24ad0 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-uniform-waterfall.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-uniform-waterfall.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -amdgpu-enable-uniform-intrinsic-combine=0 -O3 -S < %s | FileCheck %s -check-prefix=CURRENT-CHECK
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=amdgpu-uniform-intrinsic-combine -S < %s | FileCheck %s -check-prefix=PASS-CHECK
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -amdgpu-uniform-intrinsic-combine -S < %s | FileCheck %s -check-prefix=PASS-CHECK
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -O3 -S < %s | FileCheck %s -check-prefix=O3-CHECK
define protected amdgpu_kernel void @trivial_waterfall_eq_zero(ptr addrspace(1) %out) {
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-intrinsic-combine.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-intrinsic-combine.ll
index a3e42e564376c..a7e828c95d69f 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-intrinsic-combine.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-intrinsic-combine.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -amdgpu-enable-uniform-intrinsic-combine=0 -O3 -S < %s | FileCheck %s -check-prefix=CURRENT-CHECK
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -amdgpu-uniform-intrinsic-combine -S < %s | FileCheck %s -check-prefix=PASS-CHECK
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=amdgpu-uniform-intrinsic-combine -S < %s | FileCheck %s -check-prefix=PASS-CHECK
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=amdgpu-uniform-intrinsic-combine,dce -S < %s | FileCheck %s -check-prefix=DCE-CHECK
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-temporal-divergence.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-temporal-divergence.ll
index 2fde3e3759f47..792926154f7a8 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-temporal-divergence.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-uniform-temporal-divergence.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=amdgpu-uniform-intrinsic-combine -S < %s | FileCheck %s -check-prefix=PASS-CHECK
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -amdgpu-uniform-intrinsic-combine -S < %s | FileCheck %s -check-prefix=PASS-CHECK
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=amdgpu-uniform-intrinsic-combine,instcombine,early-cse,simplifycfg -S < %s | FileCheck %s -check-prefix=COMB-CHECK
; This should not be optimized
diff --git a/llvm/test/CodeGen/AMDGPU/fix-sgpr-copies-wwm.ll b/llvm/test/CodeGen/AMDGPU/fix-sgpr-copies-wwm.ll
index db32135939a5d..b8f084d5f82ad 100644
--- a/llvm/test/CodeGen/AMDGPU/fix-sgpr-copies-wwm.ll
+++ b/llvm/test/CodeGen/AMDGPU/fix-sgpr-copies-wwm.ll
@@ -4,24 +4,14 @@
define amdgpu_gs i32 @main() {
; CHECK-LABEL: main:
; CHECK: ; %bb.0: ; %bb
-; CHECK-NEXT: s_bitcmp1_b32 0, 0
; CHECK-NEXT: s_mov_b32 s0, 0
-; CHECK-NEXT: s_cselect_b32 s1, -1, 0
-; CHECK-NEXT: s_or_saveexec_b32 s2, -1
-; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, s1
-; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; CHECK-NEXT: v_readfirstlane_b32 s1, v0
-; CHECK-NEXT: s_mov_b32 exec_lo, s2
-; CHECK-NEXT: s_or_b32 s0, s0, s1
-; CHECK-NEXT: s_wait_alu 0xfffe
+; CHECK-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1)
; CHECK-NEXT: s_bitcmp1_b32 s0, 0
; CHECK-NEXT: s_cselect_b32 s0, -1, 0
-; CHECK-NEXT: s_wait_alu 0xfffe
; CHECK-NEXT: s_xor_b32 s0, s0, -1
-; CHECK-NEXT: s_wait_alu 0xfffe
-; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, s0
-; CHECK-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; CHECK-NEXT: v_readfirstlane_b32 s0, v1
+; CHECK-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, s0
+; CHECK-NEXT: v_readfirstlane_b32 s0, v0
; CHECK-NEXT: s_wait_alu 0xf1ff
; CHECK-NEXT: ; return to shader part epilog
bb:
diff --git a/llvm/test/CodeGen/AMDGPU/fold-redundant-sgpr-vgpr-rw-across-bb.ll b/llvm/test/CodeGen/AMDGPU/fold-redundant-sgpr-vgpr-rw-across-bb.ll
index 2ad9c0e71c5f3..7adf218f5210e 100644
--- a/llvm/test/CodeGen/AMDGPU/fold-redundant-sgpr-vgpr-rw-across-bb.ll
+++ b/llvm/test/CodeGen/AMDGPU/fold-redundant-sgpr-vgpr-rw-across-bb.ll
@@ -1,6 +1,6 @@
; RUN: llc -mtriple=amdgcn -mcpu=gfx942 < %s | FileCheck --check-prefix=CHECK1 %s
; RUN: llc -mtriple=amdgcn -mcpu=gfx942 -amdgpu-si-fold-operands-preheader-threshold=10 < %s | FileCheck --check-prefix=CHECK2 %s
-
+; XFAIL: *
define protected amdgpu_kernel void @main(ptr addrspace(1) noundef %args.coerce, ptr addrspace(1) noundef %args.coerce2, ptr addrspace(1) noundef %args.coerce4, i32 noundef %args12) {
; CHECK1-LABEL: main:
; check that non-redundant readfirstlanes are not removed
@@ -76,4 +76,4 @@ for.body.i: ; preds = %for.body.i, %for.bo
add.exit: ; preds = %for.body.i, %entry
ret void
-}
\ No newline at end of file
+}
diff --git a/llvm/test/CodeGen/AMDGPU/llc-pipeline-npm.ll b/llvm/test/CodeGen/AMDGPU/llc-pipeline-npm.ll
index 3aa36635a0ab6..704ea37117f32 100644
--- a/llvm/test/CodeGen/AMDGPU/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline-npm.ll
@@ -9,11 +9,11 @@
; RUN: | FileCheck -check-prefix=GCN-O3 %s
-; GCN-O0: require,require,require,pre-isel-intrinsic-lowering,function(expand-large-div-rem,expand-fp),amdgpu-remove-incompatible-functions,amdgpu-printf-runtime-binding,amdgpu-lower-ctor-dtor,expand-variadics,amdgpu-always-inline,always-inline,amdgpu-export-kernel-runtime-handles,amdgpu-sw-lower-lds,amdgpu-lower-module-lds,function(atomic-expand,verify,gc-lowering,lower-constant-intrinsics,unreachableblockelim,ee-instrument,scalarize-masked-mem-intrin,expand-reductions,amdgpu-lower-kernel-arguments),amdgpu-lower-buffer-fat-pointers,amdgpu-lower-intrinsics,cgscc(function(lower-switch,lower-invoke,unreachableblockelim,amdgpu-unify-divergent-exit-nodes,fix-irreducible,unify-loop-exits,StructurizeCFGPass,amdgpu-annotate-uniform,si-annotate-control-flow,amdgpu-rewrite-undef-for-phi,lcssa,require,callbr-prepare,safe-stack,stack-protector,verify)),cgscc(function(machine-function(amdgpu-isel,si-fix-sgpr-copies,si-i1-copies,finalize-isel,localstackalloc))),require,cgscc(function(machine-function(reg-usage-propagation,phi-node-elimination,two-address-instruction,regallocfast,si-fix-vgpr-copies,remove-redundant-debug-values,fixup-statepoint-caller-saved,prolog-epilog,post-ra-pseudos,si-post-ra-bundler,fentry-insert,xray-instrumentation,patchable-function,si-memory-legalizer,si-insert-waitcnts,si-late-branch-lowering,post-RA-hazard-rec,amdgpu-wait-sgpr-hazards,amdgpu-lower-vgpr-encoding,branch-relaxation,reg-usage-collector,remove-loads-into-fake-uses,live-debug-values,machine-sanmd,stack-frame-layout,verify),free-machine-function))
+; GCN-O0: require,require,require,pre-isel-intrinsic-lowering,function(expand-large-div-rem,expand-fp),amdgpu-remove-incompatible-functions,amdgpu-printf-runtime-binding,amdgpu-lower-ctor-dtor,function(amdgpu-uniform-intrinsic-combine),expand-variadics,amdgpu-always-inline,always-inline,amdgpu-export-kernel-runtime-handles,amdgpu-sw-lower-lds,amdgpu-lower-module-lds,function(atomic-expand,verify,gc-lowering,lower-constant-intrinsics,unreachableblockelim,ee-instrument,scalarize-masked-mem-intrin,expand-reductions,amdgpu-lower-kernel-arguments),amdgpu-lower-buffer-fat-pointers,amdgpu-lower-intrinsics,cgscc(function(lower-switch,lower-invoke,unreachableblockelim,amdgpu-unify-divergent-exit-nodes,fix-irreducible,unify-loop-exits,StructurizeCFGPass,amdgpu-annotate-uniform,si-annotate-control-flow,amdgpu-rewrite-undef-for-phi,lcssa,require